diff --git a/opal/mca/pmix/pmix1xx/pmix/VERSION b/opal/mca/pmix/pmix1xx/pmix/VERSION index 3952e1f675..5fac8bdaf6 100644 --- a/opal/mca/pmix/pmix1xx/pmix/VERSION +++ b/opal/mca/pmix/pmix1xx/pmix/VERSION @@ -30,7 +30,7 @@ greek=a1 # command, or with the date (if "git describe" fails) in the form of # "date". -repo_rev=git3c37421 +repo_rev=git69c398e # 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="Oct 02, 2015" +date="Oct 09, 2015" # The shared library version of each of PMIx's public libraries. # These versions are maintained in accordance with the "Library diff --git a/opal/mca/pmix/pmix1xx/pmix/examples/server.c b/opal/mca/pmix/pmix1xx/pmix/examples/server.c index 1822852bd0..12b7bcaa8e 100644 --- a/opal/mca/pmix/pmix1xx/pmix/examples/server.c +++ b/opal/mca/pmix/pmix1xx/pmix/examples/server.c @@ -343,26 +343,26 @@ static void errhandler(pmix_status_t status, pmix_proc_t procs[], size_t nprocs, pmix_info_t info[], size_t ninfo) { - pmix_output_verbose(2, "SERVER: ERRHANDLER CALLED WITH STATUS %d", status); + pmix_output_verbose(0, pmix_globals.debug_output, "SERVER: ERRHANDLER CALLED WITH STATUS %d", status); } static void op_callbk(pmix_status_t status, void *cbdata) { - pmix_output_verbose(2, "SERVER: OP CALLBACK CALLED WITH STATUS %d", status); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: OP CALLBACK CALLED WITH STATUS %d", status); } static void errhandler_reg_callbk (pmix_status_t status, int errhandler_ref, void *cbdata) { - pmix_output_verbose(2, "SERVER: ERRHANDLER REGISTRATION CALLBACK CALLED WITH STATUS %d, ref=%d", + pmix_output_verbose(1, pmix_globals.debug_output, "SERVER: ERRHANDLER REGISTRATION CALLBACK CALLED WITH STATUS %d, ref=%d", status, errhandler_ref); } static int connected(const pmix_proc_t *proc, void *server_object) { - pmix_output_verbose(2, "SERVER: CONNECTED %s:%d", proc->nspace, proc->rank); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: CONNECTED %s:%d", proc->nspace, proc->rank); return PMIX_SUCCESS; } @@ -370,7 +370,7 @@ static int connected(const pmix_proc_t *proc, void *server_object) static int finalized(const pmix_proc_t *proc, void *server_object, pmix_op_cbfunc_t cbfunc, void *cbdata) { - pmix_output_verbose(2, "SERVER: FINALIZED %s:%d", proc->nspace, proc->rank); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: FINALIZED %s:%d", proc->nspace, proc->rank); --wakeup; /* ensure we call the cbfunc so the proc can exit! */ if (NULL != cbfunc) { @@ -399,7 +399,7 @@ static pmix_status_t abort_fn(const pmix_proc_t *proc, pmix_status_t rc; myxfer_t *x; - pmix_output_verbose(2, "SERVER: ABORT on %s:%d", procs[0].nspace, procs[0].rank); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: ABORT on %s:%d", procs[0].nspace, procs[0].rank); /* instead of aborting the specified procs, notify them * (if they have registered their errhandler) */ @@ -423,7 +423,7 @@ static pmix_status_t abort_fn(const pmix_proc_t *proc, if (PMIX_SUCCESS != (rc = PMIx_Notify_error(status, procs, nprocs, &x->caller, 1, x->info, 2, abcbfunc, x))) { - pmix_output_verbose(1, "SERVER: FAILED NOTIFY ERROR %d", (int)rc); + pmix_output_verbose(0, pmix_globals.debug_output, "SERVER: FAILED NOTIFY ERROR %d", (int)rc); } return PMIX_SUCCESS; @@ -435,7 +435,7 @@ static int fencenb_fn(const pmix_proc_t procs[], size_t nprocs, char *data, size_t ndata, pmix_modex_cbfunc_t cbfunc, void *cbdata) { - pmix_output_verbose(2, "SERVER: FENCENB"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: FENCENB"); /* pass the provided data back to each participating proc */ if (NULL != cbfunc) { cbfunc(PMIX_SUCCESS, data, ndata, cbdata, NULL, NULL); @@ -448,7 +448,7 @@ static int dmodex_fn(const pmix_proc_t *proc, const pmix_info_t info[], size_t ninfo, pmix_modex_cbfunc_t cbfunc, void *cbdata) { - pmix_output_verbose(2, "SERVER: DMODEX"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: DMODEX"); /* we don't have any data for remote procs as this * test only runs one server - so report accordingly */ @@ -466,7 +466,7 @@ static int publish_fn(const pmix_proc_t *proc, pmix_locdat_t *p; size_t n; - pmix_output_verbose(2, "SERVER: PUBLISH"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: PUBLISH"); for (n=0; n < ninfo; n++) { p = PMIX_NEW(pmix_locdat_t); @@ -493,7 +493,7 @@ static int lookup_fn(const pmix_proc_t *proc, char **keys, pmix_pdata_t *pd; pmix_status_t ret = PMIX_ERR_NOT_FOUND; - pmix_output_verbose(2, "SERVER: LOOKUP"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: LOOKUP"); PMIX_CONSTRUCT(&results, pmix_list_t); @@ -539,7 +539,7 @@ static int unpublish_fn(const pmix_proc_t *proc, char **keys, pmix_locdat_t *p, *p2; size_t n; - pmix_output_verbose(2, "SERVER: UNPUBLISH"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: UNPUBLISH"); for (n=0; NULL != keys[n]; n++) { PMIX_LIST_FOREACH_SAFE(p, p2, &pubdata, pmix_locdat_t) { @@ -572,7 +572,7 @@ static int spawn_fn(const pmix_proc_t *proc, { myxfer_t *x; - pmix_output_verbose(2, "SERVER: SPAWN"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: SPAWN"); /* in practice, we would pass this request to the local * resource manager for launch, and then have that server @@ -595,7 +595,7 @@ static int connect_fn(const pmix_proc_t procs[], size_t nprocs, const pmix_info_t info[], size_t ninfo, pmix_op_cbfunc_t cbfunc, void *cbdata) { - pmix_output_verbose(2, "SERVER: CONNECT"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: CONNECT"); /* in practice, we would pass this request to the local * resource manager for handling */ @@ -612,7 +612,7 @@ static int disconnect_fn(const pmix_proc_t procs[], size_t nprocs, const pmix_info_t info[], size_t ninfo, pmix_op_cbfunc_t cbfunc, void *cbdata) { - pmix_output_verbose(2, "SERVER: DISCONNECT"); + pmix_output_verbose(2, pmix_globals.debug_output,"SERVER: DISCONNECT"); /* in practice, we would pass this request to the local * resource manager for handling */ @@ -627,7 +627,7 @@ static int disconnect_fn(const pmix_proc_t procs[], size_t nprocs, static int register_events_fn(const pmix_info_t info[], size_t ninfo, pmix_op_cbfunc_t cbfunc, void *cbdata) { - pmix_output_verbose(2, "SERVER: REGISTER EVENTS"); + pmix_output_verbose(2, pmix_globals.debug_output, "SERVER: REGISTER EVENTS"); /* in practice, we would pass this request to the local * resource manager for handling */ diff --git a/opal/mca/pmix/pmix1xx/pmix/include/pmi2.h b/opal/mca/pmix/pmix1xx/pmix/include/pmi2.h index a01de5f30d..7705291604 100644 --- a/opal/mca/pmix/pmix1xx/pmix/include/pmi2.h +++ b/opal/mca/pmix/pmix1xx/pmix/include/pmi2.h @@ -89,7 +89,7 @@ typedef struct PMI_keyval_t cannot access the KVS spaces of another job (this may happen, for example, if each mpiexec creates the KVS spaces for the processes that it manages). - + @*/ typedef struct PMI2_Connect_comm { int (*read)( void *buf, int maxlen, void *ctx ); @@ -107,10 +107,10 @@ typedef struct PMI2_Connect_comm { . size - number of processes in the job . rank - rank of this process in the job - appnum - which executable is this on the mpiexec commandline - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. - + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. + Notes: Initialize PMI for this process group. The value of spawned indicates whether this process was created by 'PMI2_Spawn_multiple'. 'spawned' will be non-zero @@ -121,13 +121,13 @@ int PMI2_Init(int *spawned, int *size, int *rank, int *appnum); /*@ PMI2_Finalize - finalize the Process Manager Interface - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. - + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. + Notes: Finalize PMI for this job. - + @*/ int PMI2_Finalize(void); @@ -136,17 +136,17 @@ int PMI2_Finalize(void); Return values: Non-zero if PMI2_Initialize has been called successfully, zero otherwise. - + @*/ int PMI2_Initialized(void); /*@ PMI2_Abort - abort the process group associated with this process - + Input Parameters: + flag - non-zero if all processes in this job should abort, zero otherwise - error_msg - error message to be printed - + Return values: If the abort succeeds this function will not return. Returns an MPI error code otherwise. @@ -163,7 +163,7 @@ int PMI2_Abort(int flag, const char msg[]); . argcs - size of argv arrays for each command string . argvs - array of argv arrays for each command string . maxprocs - array of maximum processes to spawn for each command string - . info_keyval_sizes - array giving the number of elements in each of the + . info_keyval_sizes - array giving the number of elements in each of the 'info_keyval_vectors' . info_keyval_vectors - array of keyval vector arrays . preput_keyval_size - Number of elements in 'preput_keyval_vector' @@ -175,7 +175,7 @@ int PMI2_Abort(int flag, const char msg[]); - errors - array of errors for each command Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Notes: This function spawns a set of processes into a new job. The 'count' @@ -184,7 +184,7 @@ int PMI2_Abort(int flag, const char msg[]); to the size of the 'preput_keyval_vector' array. The 'preput_keyval_vector' contains keyval pairs that will be put in the keyval space of the newly created job before the processes are started. The 'maxprocs' array - specifies the desired number of processes to create for each 'cmd' string. + specifies the desired number of processes to create for each 'cmd' string. The actual number of processes may be less than the numbers specified in maxprocs. The acceptable number of processes spawned may be controlled by ``soft'' keyvals in the info arrays. The ``soft'' option is specified by @@ -202,20 +202,38 @@ int PMI2_Job_Spawn(int count, const char * cmds[], int errors[]); /*@ - PMI2_Job_GetId - get job id of this job + PMI2_Job_GetId - get job id of this job Input parameters: . jobid_size - size of buffer provided in jobid Output parameters: . jobid - the job id of this job - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. @*/ int PMI2_Job_GetId(char jobid[], int jobid_size); +/*@ + PMI2_Job_GetRank - get rank of this job + Output parameters: + . rank - the rank of this job + Return values: + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. +@*/ +int PMI2_Job_GetRank(int* rank); + +/*@ + PMI2_Info_GetSize - get the number of processes on the node + Output parameters: + . rank - the rank of this job + Return values: + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. +@*/ +int PMI2_Info_GetSize(int* size); + /*@ PMI2_Job_Connect - connect to the parallel job with ID jobid @@ -225,9 +243,9 @@ int PMI2_Job_GetId(char jobid[], int jobid_size); Output parameters: . conn - connection structure used to exteblish communication with the remote job - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Notes: This just "registers" the other parallel job as part of a parallel @@ -247,7 +265,7 @@ int PMI2_Job_Connect(const char jobid[], PMI2_Connect_comm_t *conn); . jobid - job id of the job to connect to Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. @*/ int PMI2_Job_Disconnect(const char jobid[]); @@ -258,9 +276,9 @@ int PMI2_Job_Disconnect(const char jobid[]); Input Parameters: + key - key - value - value - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Notes: If multiple PMI2_KVS_Put calls are made with the same key between @@ -274,7 +292,7 @@ int PMI2_KVS_Put(const char key[], const char value[]); PMI2_KVS_Fence - commit all PMI2_KVS_Put calls made before this fence Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Notes: This is a collective call across the job. It has semantics that are @@ -287,7 +305,7 @@ int PMI2_KVS_Put(const char key[], const char value[]); their corresponding PMI2_KVS_Fence until some process issues a PMI2_KVS_Get. This might be appropriate for some wide-area implementations. - + @*/ int PMI2_KVS_Fence(void); @@ -308,9 +326,9 @@ int PMI2_KVS_Fence(void); + value - value associated with key - vallen - length of the returned value, or, if the length is longer than maxvalue, the negative of the required length is returned - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. @*/ int PMI2_KVS_Get(const char *jobid, int src_pmi_id, const char key[], char value [], int maxvalue, int *vallen); @@ -328,9 +346,9 @@ int PMI2_KVS_Get(const char *jobid, int src_pmi_id, const char key[], char value Output Parameters: + value - value of the attribute - found - non-zero indicates that the attribute was found - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Notes: This provides a way, when combined with PMI2_Info_PutNodeAttr, for @@ -367,9 +385,9 @@ int PMI2_Info_GetNodeAttr(const char name[], char value[], int valuelen, int *fo + array - value of attribute . outlen - number of elements returned - found - non-zero if attribute was found - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Notes: Notice that, unlike PMI2_Info_GetNodeAttr, this function does not @@ -398,12 +416,12 @@ int PMI2_Info_GetNodeAttrIntArray(const char name[], int array[], int arraylen, - value - the value of the attribute Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Notes: For example, it might be used to share segment ids with other processes on the same SMP node. - + @*/ int PMI2_Info_PutNodeAttr(const char name[], const char value[]); @@ -418,9 +436,9 @@ int PMI2_Info_PutNodeAttr(const char name[], const char value[]); Output Parameters: + value - value of the attribute - found - non-zero indicates that the attribute was found - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. @*/ int PMI2_Info_GetJobAttr(const char name[], char value[], int valuelen, int *found); @@ -437,9 +455,9 @@ int PMI2_Info_GetJobAttr(const char name[], char value[], int valuelen, int *fou + array - value of attribute . outlen - number of elements returned - found - non-zero if attribute was found - + Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. Predefined array attribute names: @@ -449,7 +467,7 @@ int PMI2_Info_GetJobAttr(const char name[], char value[], int valuelen, int *fou . hasNameServ - The value hasNameServ is true if the PMI2 environment supports the name service operations (publish, lookup, and unpublish). - + . physTopology - Return the topology of the underlying network. The valid topology types include cartesian, hierarchical, complete, kautz, hypercube; additional types may be added as necessary. If @@ -471,7 +489,7 @@ int PMI2_Info_GetJobAttr(const char name[], char value[], int valuelen, int *fou is cartesian,complete. All processes are connected by the cartesian part of this, but for each complete network, only the processes on the same node are connected. - + . cartDims - Return a string of comma-separated values describing the dimensions of the Cartesian topology. This must be consistent with the value of cartCoords that may be returned by @@ -482,7 +500,7 @@ int PMI2_Info_GetJobAttr(const char name[], char value[], int valuelen, int *fou PMI interface and how extensions can be added within the same API and wire protocol. For example, adding more complex network topologies requires only adding new keys, not new routines. - + . isHeterogeneous - The value isHeterogeneous is true if the processes belonging to the job are running on nodes with different underlying data models. @@ -491,7 +509,7 @@ int PMI2_Info_GetJobAttr(const char name[], char value[], int valuelen, int *fou int PMI2_Info_GetJobAttrIntArray(const char name[], int array[], int arraylen, int *outlen, int *found); /*@ - PMI2_Nameserv_publish - publish a name + PMI2_Nameserv_publish - publish a name Input parameters: + service_name - string representing the service being published @@ -499,7 +517,7 @@ int PMI2_Info_GetJobAttrIntArray(const char name[], int array[], int arraylen, i - port - string representing the port on which to contact the service Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. @*/ int PMI2_Nameserv_publish(const char service_name[], const PMI_keyval_t *info_ptr, const char port[]); @@ -511,12 +529,12 @@ int PMI2_Nameserv_publish(const char service_name[], const PMI_keyval_t *info_pt + service_name - string representing the service being published . info_ptr - - portLen - size of buffer provided in port - + Output parameters: . port - string representing the port on which to contact the service Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. @*/ int PMI2_Nameserv_lookup(const char service_name[], const PMI_keyval_t *info_ptr, @@ -529,10 +547,10 @@ int PMI2_Nameserv_lookup(const char service_name[], const PMI_keyval_t *info_ptr - info_ptr - Return values: - Returns 'MPI_SUCCESS' on success and an MPI error code on failure. + Returns 'PMI2_SUCCESS' on success and an PMI error code on failure. @*/ -int PMI2_Nameserv_unpublish(const char service_name[], +int PMI2_Nameserv_unpublish(const char service_name[], const PMI_keyval_t *info_ptr); diff --git a/opal/mca/pmix/pmix1xx/pmix/include/pmix/pmix_common.h.in b/opal/mca/pmix/pmix1xx/pmix/include/pmix/pmix_common.h.in index 48f3fbf809..0216e34aa2 100644 --- a/opal/mca/pmix/pmix1xx/pmix/include/pmix/pmix_common.h.in +++ b/opal/mca/pmix/pmix1xx/pmix/include/pmix/pmix_common.h.in @@ -470,10 +470,10 @@ typedef struct { } while(0); #define PMIX_INFO_LOAD(m, k, v, t) \ - if (NULL != (m)) { \ + do { \ (void)strncpy((m)->key, (k), PMIX_MAX_KEYLEN); \ pmix_value_load(&((m)->value), (v), (t)); \ - } + } while(0); /**** PMIX LOOKUP RETURN STRUCT ****/ diff --git a/opal/mca/pmix/pmix1xx/pmix/include/private/types.h b/opal/mca/pmix/pmix1xx/pmix/include/private/types.h index 9b45e1d9b9..e40c3687b3 100644 --- a/opal/mca/pmix/pmix1xx/pmix/include/private/types.h +++ b/opal/mca/pmix/pmix1xx/pmix/include/private/types.h @@ -10,6 +10,8 @@ * 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) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/pack.c b/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/pack.c index cf453eeaf7..be3a894111 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/pack.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/pack.c @@ -13,6 +13,8 @@ * Copyright (c) 2014-2015 Intel, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/unpack.c b/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/unpack.c index 45c8b201b7..2f7f8a4cb2 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/unpack.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/buffer_ops/unpack.c @@ -13,6 +13,8 @@ * Copyright (c) 2014-2015 Intel, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/client/pmi1.c b/opal/mca/pmix/pmix1xx/pmix/src/client/pmi1.c index 9119e97be2..808f9e3984 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/client/pmi1.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/client/pmi1.c @@ -3,6 +3,8 @@ * Copyright (c) 2014-2015 Intel, Inc. All rights reserved. * Copyright (c) 2014 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -37,53 +39,79 @@ #include "src/util/error.h" #include "src/util/output.h" +#define PMI_MAX_ID_LEN PMIX_MAX_NSLEN /* Maximim size of PMI process group ID */ +#define PMI_MAX_KEY_LEN PMIX_MAX_KEYLEN /* Maximum size of a PMI key */ +#define PMI_MAX_KVSNAME_LEN PMIX_MAX_NSLEN /* Maximum size of KVS name */ +#define PMI_MAX_VAL_LEN 4096 /* Maximum size of a PMI value */ + +#define PMI_CHECK() \ + do { \ + if (!pmi_init) { \ + return PMI_FAIL; \ + } \ + } while (0) + /* local functions */ static pmix_status_t convert_int(int *value, pmix_value_t *kv); static int convert_err(pmix_status_t rc); static pmix_proc_t myproc; static bool data_commited = false; +static int pmi_init = 0; -int PMI_Init( int *spawned ) +int PMI_Init(int *spawned) { - pmix_value_t *kv; + pmix_value_t *val; pmix_status_t rc; if (PMIX_SUCCESS != PMIx_Init(&myproc)) { return PMI_ERR_INIT; } - if (NULL == spawned) { - return PMI_SUCCESS; + if (NULL != spawned) { + /* get the spawned flag */ + if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_SPAWNED, NULL, 0, &val)) { + rc = convert_int(spawned, val); + PMIX_VALUE_RELEASE(val); + if (PMIX_SUCCESS != rc) { + return convert_err(rc); + } + } else { + /* if not found, default to not spawned */ + *spawned = 0; + } } + pmi_init = 1; - /* get the spawned flag - this will likely pull - * down all attributes assigned to the job, thus - * making all subsequent "get" operations purely - * local */ - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_SPAWNED, NULL, 0, &kv)) { - rc = convert_int(spawned, kv); - PMIX_VALUE_RELEASE(kv); - return convert_err(rc); - } - /* if it wasn't found, then default to "not spawned" */ - *spawned = 0; return PMI_SUCCESS; } int PMI_Initialized(PMI_BOOL *initialized) { - *initialized = (PMI_BOOL)PMIx_Initialized(); + if (NULL == initialized) { + return PMI_ERR_INVALID_ARG; + } + + *initialized = (PMIx_Initialized() ? PMI_TRUE : PMI_FALSE); + return PMI_SUCCESS; } int PMI_Finalize(void) { - return PMIx_Finalize(); + pmix_status_t rc = PMIX_SUCCESS; + + PMI_CHECK(); + + pmi_init = 0; + rc = PMIx_Finalize(); + return convert_err(rc); } int PMI_Abort(int flag, const char msg[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + + PMI_CHECK(); rc = PMIx_Abort(flag, msg, NULL, 0); return convert_err(rc); @@ -93,12 +121,23 @@ int PMI_Abort(int flag, const char msg[]) * provided kvsname as we only put into our own nspace */ int PMI_KVS_Put(const char kvsname[], const char key[], const char value[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_value_t val; + PMI_CHECK(); + + if ((kvsname == NULL) || (strlen(kvsname) > PMI_MAX_KVSNAME_LEN)) { + return PMI_ERR_INVALID_KVS; + } + if ((key == NULL) || (strlen(key) >PMI_MAX_KEY_LEN)) { + return PMI_ERR_INVALID_KEY; + } + if ((value == NULL) || (strlen(value) > PMI_MAX_VAL_LEN)) { + return PMI_ERR_INVALID_VAL; + } + pmix_output_verbose(2, pmix_globals.debug_output, - "PMI_KVS_Put: KVS=%s, key=%s value=%s", - kvsname, key, value); + "PMI_KVS_Put: KVS=%s, key=%s value=%s", kvsname, key, value); val.type = PMIX_STRING; val.data.string = (char*)value; @@ -109,10 +148,16 @@ int PMI_KVS_Put(const char kvsname[], const char key[], const char value[]) /* KVS_Commit */ int PMI_KVS_Commit(const char kvsname[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; - pmix_output_verbose(2, pmix_globals.debug_output, - "PMI_KVS_Commit: KVS=%s", kvsname); + PMI_CHECK(); + + if ((kvsname == NULL) || (strlen(kvsname) > PMI_MAX_KVSNAME_LEN)) { + return PMI_ERR_INVALID_KVS; + } + + pmix_output_verbose(2, pmix_globals.debug_output, "PMI_KVS_Commit: KVS=%s", + kvsname); rc = PMIx_Commit(); /* PMIx permits only one data commit! */ @@ -122,27 +167,38 @@ int PMI_KVS_Commit(const char kvsname[]) int PMI_KVS_Get( const char kvsname[], const char key[], char value[], int length) { + pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; uint32_t i; static pmix_proc_t proc; uint32_t procnum; proc = myproc; - int rc; + + PMI_CHECK(); + + if ((kvsname == NULL) || (strlen(kvsname) > PMI_MAX_KVSNAME_LEN)) { + return PMI_ERR_INVALID_KVS; + } + if ((key == NULL) || (strlen(key) >PMI_MAX_KEY_LEN)) { + return PMI_ERR_INVALID_KEY; + } + if (value == NULL) { + return PMI_ERR_INVALID_VAL; + } pmix_output_verbose(2, pmix_globals.debug_output, - "PMI_KVS_Get: KVS=%s, key=%s value=%s", - kvsname, key, value); + "PMI_KVS_Get: KVS=%s, key=%s value=%s", kvsname, key, value); /* PMI-1 expects resource manager to set * process mapping in ANL notation. */ - if( !strcmp(key, ANL_MAPPING) ) { + if (!strcmp(key, ANL_MAPPING)) { /* we are looking in the job-data. If there is nothing there * we don't want to look in rank's data, thus set rank to widcard */ proc.rank = PMIX_RANK_WILDCARD; - if( PMIX_SUCCESS == PMIx_Get(&proc, PMIX_ANL_MAP, NULL, 0, &val) && - (NULL != val) && (PMIX_STRING == val->type) ){ - strncpy(value,val->data.string,length); - PMIX_VALUE_FREE(val,1); + if (PMIX_SUCCESS == PMIx_Get(&proc, PMIX_ANL_MAP, NULL, 0, &val) && + (NULL != val) && (PMIX_STRING == val->type)) { + strncpy(value, val->data.string, length); + PMIX_VALUE_FREE(val, 1); return PMI_SUCCESS; } else { /* artpol: @@ -167,47 +223,49 @@ int PMI_KVS_Get( const char kvsname[], const char key[], char value[], int lengt * an error and don't try to use direct modex. */ - if (PMIX_SUCCESS != (rc = PMIx_Get(&myproc,PMIX_JOB_SIZE, NULL, 0,&val))) { + if (PMIX_SUCCESS != (rc = PMIx_Get(&myproc, PMIX_JOB_SIZE, NULL, 0, &val))) { pmix_output_verbose(2, pmix_globals.debug_output, - "pmi1: executing put for KVS %s, key %s value %s", - kvsname, key, value); - return convert_err(rc); + "pmi1: executing put for KVS %s, key %s value %s", kvsname, key, + value); + return convert_err(rc); } procnum = val->data.uint32; - PMIX_VALUE_FREE(val,1); + PMIX_VALUE_FREE(val, 1); - for( i=0; i < procnum; i++){ + for (i = 0; i < procnum; i++) { proc.rank = i; - if( PMIX_SUCCESS == PMIx_Get(&proc, key, NULL, 0, &val) && - (NULL != val) && (PMIX_STRING == val->type) ){ - strncpy(value,val->data.string,length); - PMIX_VALUE_FREE(val,1); + if (PMIX_SUCCESS == PMIx_Get(&proc, key, NULL, 0, &val) && (NULL != val) + && (PMIX_STRING == val->type)) { + strncpy(value, val->data.string, length); + PMIX_VALUE_FREE(val, 1); return PMI_SUCCESS; } - PMIX_VALUE_FREE(val,1); + PMIX_VALUE_FREE(val, 1); } return PMI_FAIL; } - /* Barrier only applies to our own nspace, and we want all * data to be collected upon completion */ int PMI_Barrier(void) { + pmix_status_t rc = PMIX_SUCCESS; pmix_info_t buf; - int rc, ninfo = 0; + int ninfo = 0; pmix_info_t *info = NULL; - if( data_commited ){ - bool val = 1; + PMI_CHECK(); + + if (data_commited) { + bool val = 1; info = &buf; PMIX_INFO_CONSTRUCT(info); - PMIX_INFO_LOAD(info, PMIX_COLLECT_DATA, &val, PMIX_BOOL ); + PMIX_INFO_LOAD(info, PMIX_COLLECT_DATA, &val, PMIX_BOOL); ninfo = 1; } rc = PMIx_Fence(NULL, 0, info, ninfo); - if( NULL != info ){ + if (NULL != info) { PMIX_INFO_DESTRUCT(info); } return rc; @@ -215,16 +273,18 @@ int PMI_Barrier(void) int PMI_Get_size(int *size) { - pmix_value_t *kv; - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + pmix_value_t *val; + + PMI_CHECK(); if (NULL == size) { - return PMI_FAIL; + return PMI_ERR_INVALID_ARG; } - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_JOB_SIZE, NULL, 0, &kv)) { - rc = convert_int(size, kv); - PMIX_VALUE_RELEASE(kv); + if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_JOB_SIZE, NULL, 0, &val)) { + rc = convert_int(size, val); + PMIX_VALUE_RELEASE(val); return convert_err(rc); } @@ -233,26 +293,30 @@ int PMI_Get_size(int *size) int PMI_Get_rank(int *rk) { + PMI_CHECK(); + if (NULL == rk) { - return PMI_FAIL; + return PMI_ERR_INVALID_ARG; } - *rk = pmix_globals.myid.rank; + *rk = myproc.rank; return PMI_SUCCESS; } int PMI_Get_universe_size(int *size) { - pmix_value_t *kv; - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + pmix_value_t *val; + + PMI_CHECK(); if (NULL == size) { - return PMI_FAIL; + return PMI_ERR_INVALID_ARG; } - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_UNIV_SIZE, NULL, 0, &kv)) { - rc = convert_int(size, kv); - PMIX_VALUE_RELEASE(kv); + if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_UNIV_SIZE, NULL, 0, &val)) { + rc = convert_int(size, val); + PMIX_VALUE_RELEASE(val); return convert_err(rc); } return PMI_FAIL; @@ -260,13 +324,15 @@ int PMI_Get_universe_size(int *size) int PMI_Get_appnum(int *appnum) { - pmix_value_t *kv; - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + pmix_value_t *val; + + PMI_CHECK(); if (NULL != appnum && - PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_APPNUM, NULL, 0, &kv)) { - rc = convert_int(appnum, kv); - PMIX_VALUE_RELEASE(kv); + PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_APPNUM, NULL, 0, &val)) { + rc = convert_int(appnum, val); + PMIX_VALUE_RELEASE(val); return convert_err(rc); } @@ -275,16 +341,19 @@ int PMI_Get_appnum(int *appnum) int PMI_Publish_name(const char service_name[], const char port[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_info_t info; + PMI_CHECK(); + if (NULL == service_name || NULL == port) { - return convert_err(PMIX_ERR_BAD_PARAM); + return PMI_ERR_INVALID_ARG; } + /* pass the service/port */ - (void)strncpy(info.key, service_name, PMIX_MAX_KEYLEN); + (void) strncpy(info.key, service_name, PMIX_MAX_KEYLEN); info.value.type = PMIX_STRING; - info.value.data.string = (char*)port; + info.value.data.string = (char*) port; /* publish the info - PMI-1 doesn't support * any scope other than inside our own nspace */ @@ -295,11 +364,17 @@ int PMI_Publish_name(const char service_name[], const char port[]) int PMI_Unpublish_name(const char service_name[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; char *keys[2]; + PMI_CHECK(); + + if (NULL == service_name) { + return PMI_ERR_INVALID_ARG; + } + /* pass the service */ - keys[0] = (char*)service_name; + keys[0] = (char*) service_name; keys[1] = NULL; rc = PMIx_Unpublish(keys, NULL, 0); @@ -308,13 +383,19 @@ int PMI_Unpublish_name(const char service_name[]) int PMI_Lookup_name(const char service_name[], char port[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_pdata_t pdata; + PMI_CHECK(); + + if (NULL == service_name || NULL == port) { + return PMI_ERR_INVALID_ARG; + } + PMIX_PDATA_CONSTRUCT(&pdata); /* pass the service */ - (void)strncpy(pdata.key, service_name, PMIX_MAX_KEYLEN); + (void) strncpy(pdata.key, service_name, PMIX_MAX_KEYLEN); /* PMI-1 doesn't want the nspace back */ if (PMIX_SUCCESS != (rc = PMIx_Lookup(&pdata, 1, NULL, 0))) { @@ -322,8 +403,7 @@ int PMI_Lookup_name(const char service_name[], char port[]) } /* should have received a string back */ - if (PMIX_STRING != pdata.value.type || - NULL == pdata.value.data.string) { + if (PMIX_STRING != pdata.value.type || NULL == pdata.value.data.string) { return convert_err(PMIX_ERR_NOT_FOUND); } @@ -332,7 +412,7 @@ int PMI_Lookup_name(const char service_name[], char port[]) * potential we could overrun it. As this feature * isn't widely supported in PMI-1, try being * conservative */ - (void)strncpy(port, pdata.value.data.string, PMIX_MAX_KEYLEN); + (void) strncpy(port, pdata.value.data.string, PMIX_MAX_KEYLEN); PMIX_PDATA_DESTRUCT(&pdata); return PMIX_SUCCESS; @@ -343,37 +423,54 @@ int PMI_Get_id(char id_str[], int length) /* we already obtained our nspace during PMI_Init, * so all we have to do here is return it */ + PMI_CHECK(); + /* bozo check */ if (NULL == id_str) { return PMI_ERR_INVALID_ARGS; } - (void)strncpy(id_str, pmix_globals.myid.nspace, length); + if (length < PMI_MAX_ID_LEN) { + return PMI_ERR_INVALID_LENGTH; + } + + (void) strncpy(id_str, myproc.nspace, length); return PMI_SUCCESS; } int PMI_Get_kvs_domain_id(char id_str[], int length) { + PMI_CHECK(); + /* same as PMI_Get_id */ return PMI_Get_id(id_str, length); } int PMI_Get_id_length_max(int *length) { + PMI_CHECK(); + if (NULL == length) { return PMI_ERR_INVALID_VAL_LENGTH; } - *length = PMIX_MAX_KEYLEN; + + *length = PMI_MAX_ID_LEN; return PMI_SUCCESS; } int PMI_Get_clique_size(int *size) { - pmix_value_t *kv; - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + pmix_value_t *val; - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_LOCAL_SIZE, NULL, 0, &kv)) { - rc = convert_int(size, kv); - PMIX_VALUE_RELEASE(kv); + PMI_CHECK(); + + if (NULL == size) { + return PMI_ERR_INVALID_ARGS; + } + + if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_LOCAL_SIZE, NULL, 0, &val)) { + rc = convert_int(size, val); + PMIX_VALUE_RELEASE(val); return convert_err(rc); } @@ -382,19 +479,25 @@ int PMI_Get_clique_size(int *size) int PMI_Get_clique_ranks(int ranks[], int length) { - pmix_value_t *kv; + pmix_value_t *val; char **rks; int i; - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_LOCAL_PEERS, NULL, 0, &kv)) { + PMI_CHECK(); + + if (NULL == ranks) { + return PMI_ERR_INVALID_ARGS; + } + + if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_LOCAL_PEERS, NULL, 0, &val)) { /* kv will contain a string of comma-separated * ranks on my node */ - rks = pmix_argv_split(kv->data.string, ','); - for (i=0; NULL != rks[i] && i < length; i++) { + rks = pmix_argv_split(val->data.string, ','); + for (i = 0; NULL != rks[i] && i < length; i++) { ranks[i] = strtol(rks[i], NULL, 10); } pmix_argv_free(rks); - PMIX_VALUE_RELEASE(kv); + PMIX_VALUE_RELEASE(val); return PMI_SUCCESS; } return PMI_FAIL; @@ -402,36 +505,47 @@ int PMI_Get_clique_ranks(int ranks[], int length) int PMI_KVS_Get_my_name(char kvsname[], int length) { + PMI_CHECK(); + /* same as PMI_Get_id */ return PMI_Get_id(kvsname, length); } int PMI_KVS_Get_name_length_max(int *length) { - if (NULL == length) { - return PMI_ERR_INVALID_VAL_LENGTH; + PMI_CHECK(); + + if (NULL == length) { + return PMI_ERR_INVALID_ARG; } - *length = PMIX_MAX_NSLEN; + + *length = PMI_MAX_KVSNAME_LEN; return PMI_SUCCESS; } int PMI_KVS_Get_key_length_max(int *length) { + PMI_CHECK(); + if (NULL == length) { - return PMI_ERR_INVALID_VAL_LENGTH; + return PMI_ERR_INVALID_ARG; } - *length = PMIX_MAX_KEYLEN; + + *length = PMI_MAX_KEY_LEN; return PMI_SUCCESS; } int PMI_KVS_Get_value_length_max(int *length) { + PMI_CHECK(); + if (NULL == length) { - return PMI_ERR_INVALID_VAL_LENGTH; + return PMI_ERR_INVALID_ARG; } + /* don't give them an enormous size of some implementations * immediately malloc a data block for their use */ - *length = 4096; + *length = PMI_MAX_VAL_LEN; return PMI_SUCCESS; } @@ -473,31 +587,37 @@ int PMI_Spawn_multiple(int count, const PMI_keyval_t preput_keyval_vector[], int errors[]) { + pmix_status_t rc = PMIX_SUCCESS; pmix_app_t *apps; int i, k; - pmix_status_t rc; size_t j; char *evar; + PMI_CHECK(); + + if (NULL == cmds) { + return PMI_ERR_INVALID_ARG; + } + /* setup the apps */ PMIX_APP_CREATE(apps, count); - for (i=0; i < count; i++) { + for (i = 0; i < count; i++) { apps[i].cmd = strdup(cmds[i]); apps[i].maxprocs = maxprocs[i]; - apps[i].argv = pmix_argv_copy((char**)argvs[i]); + apps[i].argv = pmix_argv_copy((char**) argvs[i]); apps[i].argc = pmix_argv_count(apps[i].argv); apps[i].ninfo = info_keyval_sizesp[i]; if (0 < apps[i].ninfo) { apps[i].info = (pmix_info_t*)malloc(apps[i].ninfo * sizeof(pmix_info_t)); /* copy the info objects */ - for (j=0; j < apps[i].ninfo; j++) { + for (j = 0; j < apps[i].ninfo; j++) { (void)strncpy(apps[i].info[j].key, info_keyval_vectors[i][j].key, PMIX_MAX_KEYLEN); apps[i].info[j].value.type = PMIX_STRING; apps[i].info[j].value.data.string = strdup(info_keyval_vectors[i][j].val); } } /* push the preput values into the apps environ */ - for (k=0; k < preput_keyval_size; k++) { + for (k = 0; k < preput_keyval_size; k++) { (void)asprintf(&evar, "%s=%s", preput_keyval_vector[k].key, preput_keyval_vector[k].val); pmix_argv_append_nosize(&apps[i].env, evar); free(evar); @@ -506,12 +626,12 @@ int PMI_Spawn_multiple(int count, rc = PMIx_Spawn(NULL, 0, apps, count, NULL); /* tear down the apps array */ - for (i=0; i < count; i++) { + for (i = 0; i < count; i++) { PMIX_APP_DESTRUCT(&apps[i]); } free(apps); if (NULL != errors) { - for (i=0; i < count; i++) { + for (i = 0; i < count; i++) { errors[i] = convert_err(rc); } } @@ -546,12 +666,11 @@ int PMI_Get_options(char *str, int *length) return PMI_FAIL; } - /*** UTILITY FUNCTIONS ***/ /* internal function */ static pmix_status_t convert_int(int *value, pmix_value_t *kv) { - switch(kv->type) { + switch (kv->type) { case PMIX_INT: *value = kv->data.integer; break; @@ -600,7 +719,7 @@ static pmix_status_t convert_int(int *value, pmix_value_t *kv) static int convert_err(pmix_status_t rc) { - switch(rc) { + switch (rc) { case PMIX_ERR_INVALID_SIZE: return PMI_ERR_INVALID_SIZE; diff --git a/opal/mca/pmix/pmix1xx/pmix/src/client/pmi2.c b/opal/mca/pmix/pmix1xx/pmix/src/client/pmi2.c index 964bc43c76..7c9df035af 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/client/pmi2.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/client/pmi2.c @@ -1,8 +1,10 @@ /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2014-2015 Intel, Inc. All rights reserved. - * Copyright (c) 2014-2015 Research Organization for Information Science + * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -35,15 +37,24 @@ #include "src/util/error.h" #include "src/util/output.h" +#define PMI2_CHECK() \ + do { \ + if (!pmi2_init) { \ + return PMI2_FAIL; \ + } \ + } while (0) + /* local functions */ static pmix_status_t convert_int(int *value, pmix_value_t *kv); static int convert_err(pmix_status_t rc); static pmix_proc_t myproc; +static int pmi2_init = 0; int PMI2_Init(int *spawned, int *size, int *rank, int *appnum) { - pmix_value_t *kv; - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + pmix_value_t *val; + pmix_proc_t proc; if (PMIX_SUCCESS != PMIx_Init(&myproc)) { return PMI2_ERR_INIT; @@ -52,14 +63,18 @@ int PMI2_Init(int *spawned, int *size, int *rank, int *appnum) /* get the rank */ *rank = myproc.rank; + /* getting internal key requires special rank value */ + memcpy(&proc, &myproc, sizeof(myproc)); + proc.rank = PMIX_RANK_WILDCARD; + if (NULL != size) { /* get the universe size - this will likely pull * down all attributes assigned to the job, thus * making all subsequent "get" operations purely * local */ - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_UNIV_SIZE, NULL, 0, &kv)) { - rc = convert_int(size, kv); - PMIX_VALUE_RELEASE(kv); + if (PMIX_SUCCESS == PMIx_Get(&proc, PMIX_UNIV_SIZE, NULL, 0, &val)) { + rc = convert_int(size, val); + PMIX_VALUE_RELEASE(val); if (PMIX_SUCCESS != rc) { goto error; } @@ -71,9 +86,9 @@ int PMI2_Init(int *spawned, int *size, int *rank, int *appnum) if (NULL != spawned) { /* get the spawned flag */ - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_SPAWNED, NULL, 0, &kv)) { - rc = convert_int(spawned, kv); - PMIX_VALUE_RELEASE(kv); + if (PMIX_SUCCESS == PMIx_Get(&proc, PMIX_SPAWNED, NULL, 0, &val)) { + rc = convert_int(spawned, val); + PMIX_VALUE_RELEASE(val); if (PMIX_SUCCESS != rc) { goto error; } @@ -85,9 +100,9 @@ int PMI2_Init(int *spawned, int *size, int *rank, int *appnum) if (NULL != appnum) { /* get our appnum */ - if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_APPNUM, NULL, 0, &kv)) { - rc = convert_int(appnum, kv); - PMIX_VALUE_RELEASE(kv); + if (PMIX_SUCCESS == PMIx_Get(&proc, PMIX_APPNUM, NULL, 0, &val)) { + rc = convert_int(appnum, val); + PMIX_VALUE_RELEASE(val); if (PMIX_SUCCESS != rc) { goto error; } @@ -96,6 +111,7 @@ int PMI2_Init(int *spawned, int *size, int *rank, int *appnum) *appnum = 0; } } + pmi2_init = 1; return PMI2_SUCCESS; @@ -112,15 +128,20 @@ int PMI2_Initialized(void) int PMI2_Finalize(void) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + PMI2_CHECK(); + + pmi2_init = 0; rc = PMIx_Finalize(); return convert_err(rc); } int PMI2_Abort(int flag, const char msg[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + + PMI2_CHECK(); rc = PMIx_Abort(flag, msg, NULL, 0); return convert_err(rc); @@ -129,9 +150,18 @@ int PMI2_Abort(int flag, const char msg[]) /* KVS_Put - we default to PMIX_GLOBAL scope */ int PMI2_KVS_Put(const char key[], const char value[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_value_t val; + PMI2_CHECK(); + + if ((NULL == key) || (NULL == value)) { + return PMI2_ERR_INVALID_ARG; + } + + pmix_output_verbose(3, pmix_globals.debug_output, + "PMI2_KVS_Put: key=%s value=%s", key, value); + val.type = PMIX_STRING; val.data.string = (char*)value; rc = PMIx_Put(PMIX_GLOBAL, key, &val); @@ -141,14 +171,26 @@ int PMI2_KVS_Put(const char key[], const char value[]) /* KVS_Fence */ int PMI2_KVS_Fence(void) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; + + PMI2_CHECK(); if (PMIX_SUCCESS != (rc = PMIx_Commit())) { return convert_err(rc); } /* we want all data to be collected upon completion */ - rc = PMIx_Fence(NULL, 0, NULL, 0); + { + pmix_info_t info; + int ninfo = 1; + bool val = 1; + + PMIX_INFO_CONSTRUCT(&info); + PMIX_INFO_LOAD(&info, PMIX_COLLECT_DATA, &val, PMIX_BOOL); + rc = PMIx_Fence(NULL, 0, &info, ninfo); + PMIX_INFO_DESTRUCT(&info); + } + return convert_err(rc); } @@ -161,33 +203,68 @@ int PMI2_KVS_Get(const char *jobid, int src_pmi_id, const char key[], char value [], int maxvalue, int *vallen) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; pmix_proc_t proc; + uint32_t procnum = 0; - (void)strncpy(proc.nspace, (jobid ? jobid : myproc.nspace), sizeof(myproc.nspace)); - proc.rank = (src_pmi_id == PMI2_ID_NULL ? myproc.rank : src_pmi_id); - rc = PMIx_Get(&proc, key, NULL, 0, &val); - if (PMIX_SUCCESS == rc && NULL != val) { - if (PMIX_STRING != val->type) { - /* this is an error */ - PMIX_VALUE_RELEASE(val); - return PMI2_FAIL; - } - if (NULL != val->data.string) { - (void)strncpy(value, val->data.string, maxvalue); - *vallen = strlen(val->data.string); - } - PMIX_VALUE_RELEASE(val); + PMI2_CHECK(); + + if ((NULL == key) || (NULL == value)) { + return PMI2_ERR_INVALID_ARG; } + + pmix_output_verbose(3, pmix_globals.debug_output, + "PMI2_KVS_Get: key=%s jobid=%s src_pmi_id=%d", key, (jobid ? jobid : "null"), src_pmi_id); + + (void)strncpy(proc.nspace, (jobid ? jobid : myproc.nspace), PMIX_MAX_NSLEN); + if (src_pmi_id == PMI2_ID_NULL) { + proc.rank = PMIX_RANK_WILDCARD; + if (PMIX_SUCCESS != (rc = PMIx_Get(&myproc, PMIX_JOB_SIZE, NULL, 0, &val))) { + return convert_err(rc); + } + procnum = val->data.uint32; + PMIX_VALUE_RELEASE(val); + proc.rank = 0; + } else { + proc.rank = src_pmi_id; + } + + do { + rc = PMIx_Get(&proc, key, NULL, 0, &val); + if (PMIX_SUCCESS == rc && NULL != val) { + if (PMIX_STRING != val->type) { + /* this is an error */ + PMIX_VALUE_RELEASE(val); + return PMI2_FAIL; + } + if (NULL != val->data.string) { + (void)strncpy(value, val->data.string, maxvalue); + *vallen = strlen(val->data.string); + } + PMIX_VALUE_RELEASE(val); + break; + } else if (PMIX_ERR_NOT_FOUND == rc) { + proc.rank++; + } else { + break; + } + } while (proc.rank < (int)procnum); + return convert_err(rc); } int PMI2_Info_GetNodeAttr(const char name[], char value[], int valuelen, int *found, int waitfor) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; + PMI2_CHECK(); + + if ((NULL == name) || (NULL == value) || (NULL == found)) { + return PMI2_ERR_INVALID_ARG; + } + *found = 0; rc = PMIx_Get(&myproc, name, NULL, 0, &val); if (PMIX_SUCCESS == rc && NULL != val) { @@ -210,9 +287,15 @@ int PMI2_Info_GetNodeAttr(const char name[], char value[], int valuelen, int *fo /* push info at the PMIX_LOCAL scope */ int PMI2_Info_PutNodeAttr(const char name[], const char value[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_value_t val; + PMI2_CHECK(); + + if ((NULL == name) || (NULL == value)) { + return PMI2_ERR_INVALID_ARG; + } + val.type = PMIX_STRING; val.data.string = (char*)value; rc = PMIx_Put(PMIX_LOCAL, name, &val); @@ -221,11 +304,22 @@ int PMI2_Info_PutNodeAttr(const char name[], const char value[]) int PMI2_Info_GetJobAttr(const char name[], char value[], int valuelen, int *found) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; + pmix_proc_t proc; + + PMI2_CHECK(); + + if ((NULL == name) || (NULL == value) || (NULL == found)) { + return PMI2_ERR_INVALID_ARG; + } + + /* getting internal key requires special rank value */ + memcpy(&proc, &myproc, sizeof(myproc)); + proc.rank = PMIX_RANK_WILDCARD; *found = 0; - rc = PMIx_Get(&myproc, name, NULL, 0, &val); + rc = PMIx_Get(&proc, name, NULL, 0, &val); if (PMIX_SUCCESS == rc && NULL != val) { if (PMIX_STRING != val->type) { /* this is an error */ @@ -250,13 +344,16 @@ int PMI2_Info_GetJobAttrIntArray(const char name[], int array[], int arraylen, i int PMI2_Nameserv_publish(const char service_name[], const PMI_keyval_t *info_ptr, const char port[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; int nvals; pmix_info_t info[2]; + PMI2_CHECK(); + if (NULL == service_name || NULL == port) { return PMI2_ERR_INVALID_ARG; } + /* pass the service/port */ (void)strncpy(info[0].key, service_name, PMIX_MAX_KEYLEN); info[0].value.type = PMIX_STRING; @@ -280,8 +377,14 @@ int PMI2_Nameserv_publish(const char service_name[], const PMI_keyval_t *info_pt int PMI2_Nameserv_unpublish(const char service_name[], const PMI_keyval_t *info_ptr) { + pmix_status_t rc = PMIX_SUCCESS; char *keys[3]; - pmix_status_t rc; + + PMI2_CHECK(); + + if (NULL == service_name || NULL == info_ptr) { + return PMI2_ERR_INVALID_ARG; + } /* pass the service */ keys[0] = (char*)service_name; @@ -300,10 +403,16 @@ int PMI2_Nameserv_unpublish(const char service_name[], int PMI2_Nameserv_lookup(const char service_name[], const PMI_keyval_t *info_ptr, char port[], int portLen) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; int nvals; pmix_pdata_t pdata[2]; + PMI2_CHECK(); + + if (NULL == service_name || NULL == info_ptr || NULL == port) { + return PMI2_ERR_INVALID_ARG; + } + PMIX_PDATA_CONSTRUCT(&pdata[0]); PMIX_PDATA_CONSTRUCT(&pdata[1]); @@ -347,9 +456,11 @@ int PMI2_Nameserv_lookup(const char service_name[], const PMI_keyval_t *info_ptr int PMI2_Job_GetId(char jobid[], int jobid_size) { - /* we already obtained our nspace during PMI_Init, + /* we already obtained our nspace during pmi2_init, * so all we have to do here is return it */ + PMI2_CHECK(); + /* bozo check */ if (NULL == jobid) { return PMI2_ERR_INVALID_ARGS; @@ -358,11 +469,48 @@ int PMI2_Job_GetId(char jobid[], int jobid_size) return PMI2_SUCCESS; } +int PMI2_Job_GetRank(int *rank) +{ + PMI2_CHECK(); + + if (NULL == rank) { + return PMI2_ERR_INVALID_ARGS; + } + *rank = myproc.rank; + return PMI2_SUCCESS; +} + +int PMI2_Info_GetSize(int *size) +{ + pmix_status_t rc = PMIX_SUCCESS; + pmix_value_t *val; + + PMI2_CHECK(); + + if (NULL == size) { + return PMI2_ERR_INVALID_ARGS; + } + + if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_LOCAL_SIZE, NULL, 0, &val)) { + rc = convert_int(size, val); + PMIX_VALUE_RELEASE(val); + return convert_err(rc); + } + + return PMI2_FAIL; +} + int PMI2_Job_Connect(const char jobid[], PMI2_Connect_comm_t *conn) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_proc_t proc; + PMI2_CHECK(); + + if (NULL == jobid || NULL == conn) { + return PMI2_ERR_INVALID_ARGS; + } + (void)strncpy(proc.nspace, (jobid ? jobid : myproc.nspace), sizeof(myproc.nspace)); proc.rank = PMIX_RANK_WILDCARD; rc = PMIx_Connect(&proc, 1, NULL, 0); @@ -371,9 +519,15 @@ int PMI2_Job_Connect(const char jobid[], PMI2_Connect_comm_t *conn) int PMI2_Job_Disconnect(const char jobid[]) { - pmix_status_t rc; + pmix_status_t rc = PMIX_SUCCESS; pmix_proc_t proc; + PMI2_CHECK(); + + if (NULL == jobid) { + return PMI2_ERR_INVALID_ARGS; + } + (void)strncpy(proc.nspace, (jobid ? jobid : myproc.nspace), sizeof(myproc.nspace)); proc.rank = PMIX_RANK_WILDCARD; rc = PMIx_Disconnect(&proc, 1, NULL, 0); @@ -390,12 +544,18 @@ int PMI2_Job_Spawn(int count, const char * cmds[], char jobId[], int jobIdSize, int errors[]) { + pmix_status_t rc = PMIX_SUCCESS; pmix_app_t *apps; int i, k; - pmix_status_t rc; size_t j; char *evar; + PMI2_CHECK(); + + if (NULL == cmds) { + return PMI2_ERR_INVALID_ARGS; + } + /* setup the apps */ PMIX_APP_CREATE(apps, count); for (i=0; i < count; i++) { diff --git a/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client.c b/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client.c index fcd08de9d0..1cf053eebd 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client.c @@ -5,6 +5,8 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2014 Artem Y. Polyakov . * All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_fence.c b/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_fence.c index d36a1ade8a..55078ebf38 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_fence.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_fence.c @@ -5,6 +5,8 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2014 Artem Y. Polyakov . * All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_get.c b/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_get.c index b3cc2fdff6..d41be9cbe3 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_get.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/client/pmix_client_get.c @@ -5,6 +5,8 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2014 Artem Y. Polyakov . * All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server.c b/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server.c index 8eb6966849..d16ae16212 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server.c @@ -5,6 +5,8 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2014-2015 Artem Y. Polyakov . * All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.c b/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.c index e76c557b38..4a4abd1074 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.c @@ -5,6 +5,8 @@ * and Technology (RIST). All rights reserved. * Copyright (c) 2014-2015 Artem Y. Polyakov . * All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.h b/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.h index 21091b6783..c6279d5392 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.h +++ b/opal/mca/pmix/pmix1xx/pmix/src/server/pmix_server_ops.h @@ -3,6 +3,8 @@ * Copyright (c) 2015 Intel, Inc. All rights reserved * Copyright (c) 2015 Artem Y. Polyakov . * All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ */ diff --git a/opal/mca/pmix/pmix1xx/pmix/src/usock/usock.c b/opal/mca/pmix/pmix1xx/pmix/src/usock/usock.c index b78a124d7e..5156f6a3aa 100644 --- a/opal/mca/pmix/pmix1xx/pmix/src/usock/usock.c +++ b/opal/mca/pmix/pmix1xx/pmix/src/usock/usock.c @@ -4,6 +4,8 @@ * All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/pmi2_client.c b/opal/mca/pmix/pmix1xx/pmix/test/pmi2_client.c index 759be74e82..7fed631a28 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/pmi2_client.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/pmi2_client.c @@ -1,19 +1,7 @@ /* - * Copyright (c) 2004-2010 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) 2006-2013 Los Alamos National Security, LLC. - * 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-2014 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -74,6 +62,8 @@ static int test_item5(void); static int test_item6(void); static int test_item7(void); static int test_item8(void); +/* several sequence of fences is a buggy case for pmix v1.0 (see https://github.com/open-mpi/pmix/issues/37) */ +static int test_item9(void); static int spawned, size, rank, appnum; static char jobid[100]; @@ -149,6 +139,12 @@ int main(int argc, char **argv) log_info("TI8 : %s\n", (rc ? "FAIL" : "PASS")); } + if (!ti || 9 == ti) { + rc = test_item9(); + ret += (rc ? 1 : 0); + log_info("TI9 : %s\n", (rc ? "FAIL" : "PASS")); + } + if (PMI2_SUCCESS != (rc = PMI2_Finalize())) { log_fatal("PMI2_Finalize failed: %d\n", rc); return rc; @@ -160,6 +156,7 @@ int main(int argc, char **argv) static int test_item1(void) { int rc = 0; + int val = 0; log_info("spawned=%d size=%d rank=%d appnum=%d\n", spawned, size, rank, appnum); @@ -175,9 +172,22 @@ static int test_item1(void) } log_info("jobid=%s\n", jobid); - log_assert(memcmp(jobid, __FUNCTION__, sizeof(__FUNCTION__)), ""); + val = random_value(10, 100); + if (PMI2_SUCCESS != (rc = PMI2_Job_GetRank(&val))) { + log_fatal("PMI2_Job_GetRank failed: %d\n", rc); + return rc; + } + log_assert(rank == val, ""); + + val = -1; + if (PMI2_SUCCESS != (rc = PMI2_Info_GetSize(&val))) { + log_fatal("PMI2_Info_GetSize failed: %d\n", rc); + return rc; + } + log_assert(0 < val, ""); + return rc; } @@ -333,8 +343,8 @@ static int test_item7(void) return rc; } - if (PMI2_SUCCESS != (rc = PMI2_KVS_Get(jobid, PMI2_ID_NULL, tkey, val, sizeof(val), &len))) { - log_fatal("PMI2_KVS_Get %d\n", rc); + if (PMI2_SUCCESS != (rc = PMI2_KVS_Get(jobid, i, tkey, val, sizeof(val), &len))) { + log_fatal("PMI2_KVS_Get [%s=?] %d\n", tkey, rc); return rc; } @@ -348,18 +358,58 @@ static int test_item7(void) } static int test_item8(void) +{ + int rc = 0; + int len; + char tkey[PMI2_MAX_VALLEN]; + char tval[PMI2_MAX_VALLEN]; + char val[PMI2_MAX_VALLEN]; + int i = 0; + + for (i = 0; i < size; i++) { + sprintf(tkey, "KEY-%d", i); + sprintf(tval, "VALUE-%d", i); + if (i == rank) { + if (PMI2_SUCCESS != (rc = PMI2_KVS_Put(tkey, tval))) { + log_fatal("PMI2_KVS_Put [%s=%s] %d\n", tkey, tval, rc); + return rc; + } + } + + if (PMI2_SUCCESS != (rc = PMI2_KVS_Fence())) { + log_fatal("PMI2_KVS_Fence %d\n", rc); + return rc; + } + + if (PMI2_SUCCESS != (rc = PMI2_KVS_Get(jobid, PMI2_ID_NULL, tkey, val, sizeof(val), &len))) { + log_fatal("PMI2_KVS_Get [%s=?] %d\n", tkey, rc); + return rc; + } + + log_info("tkey=%s tval=%s val=%s len=%d\n", tkey, tval, val, len); + + log_assert((int)strlen(tval) == len, "value does not meet expectation"); + log_assert(!strcmp(tval, val), "value does not meet expectation"); + } + + return rc; +} + +static int test_item9(void) { int rc = 0; int i, j, r; char symb, symb_start = 'a'; int fence_cnt; int fence_num = random_value(2, 10); - int keys_per_fence = random_value(10, 1000); - int val_size = random_value(10, PMI2_MAX_VALLEN); + int keys_per_fence = random_value(10, 100); + int val_size = random_value(10, PMI2_MAX_VALLEN / 10); int keys_total = 0; fence_cnt = 0; while (fence_cnt < fence_num) { + log_info("fence_cnt=%d of fence_num=%d keys_per_fence=%d keys_total=%d val_size=%d\n", + fence_cnt, fence_num, keys_per_fence, keys_total, val_size); symb = symb_start; for (i = 0; i < keys_per_fence; i++) { char key[PMI2_MAX_KEYLEN]; @@ -376,6 +426,7 @@ static int test_item8(void) log_fatal("PMI2_KVS_Put [%s=%s] %d\n", key, val, rc); return rc; } + log_info("PMI2_KVS_Put [rank=%d %s] %d\n", rank, key, rc); } symb_start = symb; keys_total += keys_per_fence; @@ -393,11 +444,13 @@ static int test_item8(void) char val[PMI2_MAX_VALLEN] = ""; sprintf(key, "RANK%d-key-%d", r, i); - if (PMI2_SUCCESS != (rc = PMI2_KVS_Get(jobid, PMI2_ID_NULL, key, val, sizeof(val), &len))) { - log_fatal("PMI2_KVS_Get %d\n", rc); + if (PMI2_SUCCESS != (rc = PMI2_KVS_Get(jobid, r, key, val, sizeof(val), &len))) { + log_fatal("PMI2_KVS_Get [%s=?] %d\n", key, rc); return rc; } + log_info("PMI2_KVS_Get [rank=%d %s] %d\n", rank, key, rc); + if (len != val_size) { log_fatal("%d: failure on rank %d, key #%d: len mismatch:" " %d instead of %d\n", rank, r, i, len, val_size); diff --git a/opal/mca/pmix/pmix1xx/pmix/test/pmi_client.c b/opal/mca/pmix/pmix1xx/pmix/test/pmi_client.c index 8ea0de49c3..0bfe837513 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/pmi_client.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/pmi_client.c @@ -1,19 +1,7 @@ /* - * Copyright (c) 2004-2010 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) 2006-2013 Los Alamos National Security, LLC. - * 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-2014 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow @@ -24,53 +12,411 @@ #include #include +#include +#include #include "pmi.h" +/* Target is legacy SLURM pmi library implementation */ +static int _legacy = 0; +/* Verbose level 0-silent, 1-fatal, 2-error, 3+ debug*/ +static int _verbose = 1; + +#define log_fatal(fmt, ...) \ + do { \ + if (_verbose > 0) \ + fprintf(stderr, "FATAL " fmt, ##__VA_ARGS__); \ + exit(rc); \ + } while (0) + +#define log_error(fmt) \ + do { \ + if (_verbose > 1) \ + fprintf(stderr, "ERROR " fmt); \ + } while (0) + +#define log_info(fmt, ...) \ + do { \ + if (_verbose > 2) \ + fprintf(stderr, "INFO " fmt, ##__VA_ARGS__); \ + } while (0) + +#define log_assert(e, msg) \ + do { \ + if (!(e)) { \ + log_fatal("%s at %s:%d\n", msg, __FUNCTION__, __LINE__); \ + rc = -1; \ + } \ + } while (0) + +static inline long random_value(long min_value, long max_value) +{ + return ((min_value >= max_value) ? min_value : min_value + (rand() % (max_value - min_value + 1))); +} + +static int test_item1(void); +static int test_item2(void); +static int test_item3(void); +static int test_item4(void); +static int test_item5(void); +static int test_item6(void); +static int test_item7(void); +static int test_item8(void); + +static int spawned, size, rank, appnum; +static char jobid[255]; + + int main(int argc, char **argv) { - int spawned; + int ret = 0; int rc; + char *str = NULL; + int ti = (argc > 1 ? atoi(argv[1]) : 0); - /* init us */ + srand(time(NULL)); + str = getenv("VERBOSE"); + _verbose = (str ? atoi(str) : _verbose); + str = getenv("LEGACY"); + _legacy = (str ? atoi(str) : _legacy); + + spawned = random_value(10, 20); + size = random_value(10, 20); + rank = random_value(10, 20); + appnum = random_value(10, 20); if (PMI_SUCCESS != (rc = PMI_Init(&spawned))) { - fprintf(stderr, "PMI_Init failed: %d\n", rc); + log_fatal("PMI_Init failed: %d\n", rc); return rc; } -#if 0 - key = "local-key"; - PMIX_VAL_SET(&value, int, 12345, rc, kvp_error ); - if (PMIX_SUCCESS != (rc = PMIx_Put(PMIX_LOCAL, key, &value))) { - fprintf(stderr, "PMIx_Put failed: %d\n", rc); + + /* this test should be always run */ + if (1) { + rc = test_item1(); + ret += (rc ? 1 : 0); + log_info("TI1 : %s\n", (rc ? "FAIL" : "PASS")); } - key = "remote-key"; - char *ptr = "Test string"; - PMIX_VAL_SET(&value, string, ptr, rc, kvp_error ); - if (PMIX_SUCCESS != (rc = PMIx_Put(PMIX_REMOTE, key, &value))) { - fprintf(stderr, "PMIx_Put failed: %d\n", rc); + if (!ti || 2 == ti) { + rc = test_item2(); + ret += (rc ? 1 : 0); + log_info("TI2 : %s\n", (rc ? "FAIL" : "PASS")); } - key = "global-key"; - PMIX_VAL_SET(&value, float, 10.15, rc, kvp_error ); - if (PMIX_SUCCESS != (rc = PMIx_Put(PMIX_GLOBAL, key, &value))) { - fprintf(stderr, "PMIx_Put failed: %d\n", rc); + if (!ti || 3 == ti) { + rc = test_item3(); + ret += (rc ? 1 : 0); + log_info("TI3 : %s\n", (rc ? "FAIL" : "PASS")); } - /* Submit the data */ - pmix_range_t range; - range.ranks = NULL; - range.nranks = 0; - if (PMIX_SUCCESS != (rc = PMIx_Fence(NULL, 0))) { - fprintf(stderr, "PMIx_Fence failed: %d\n", rc); - return rc; + if (!ti || 4 == ti) { + rc = test_item4(); + ret += (rc ? 1 : 0); + log_info("TI4 : %s\n", (rc ? "FAIL" : "PASS")); } -#endif - /* finalize us */ + + if (!ti || 5 == ti) { + rc = test_item5(); + ret += (rc ? 1 : 0); + log_info("TI5 : %s\n", (rc ? "FAIL" : "PASS")); + } + + if (!ti || 6 == ti) { + rc = test_item6(); + ret += (rc ? 1 : 0); + log_info("TI6 : %s\n", (rc ? "FAIL" : "PASS")); + } + + if (!ti || 7 == ti) { + rc = test_item7(); + ret += (rc ? 1 : 0); + log_info("TI7 : %s\n", (rc ? "FAIL" : "PASS")); + } + + if (!ti || 8 == ti) { + rc = test_item8(); + ret += (rc ? 1 : 0); + log_info("TI8 : %s\n", (rc ? "FAIL" : "PASS")); + } + if (PMI_SUCCESS != (rc = PMI_Finalize())) { - fprintf(stderr, "PMI_Finalize failed: %d\n", rc); + log_fatal("PMI_Finalize failed: %d\n", rc); + return rc; } - + + return ret; +} + +static int test_item1(void) +{ + int rc = 0; + int val = 0; + + log_assert(spawned == PMI_FALSE || spawned == PMI_TRUE, ""); + + if (PMI_SUCCESS != (rc = PMI_Get_size(&size))) { + log_fatal("PMI_Get_Size failed: %d\n", rc); + return rc; + } + log_assert(size >= 0, ""); + + if (PMI_SUCCESS != (rc = PMI_Get_rank(&rank))) { + log_fatal("PMI_Get_Rank failed: %d\n", rc); + return rc; + } + log_assert(rank >= 0, ""); + log_assert(rank < size, ""); + + if (PMI_SUCCESS != (rc = PMI_Get_appnum(&appnum))) { + log_fatal("PMI_Get_appnum failed: %d\n", rc); + return rc; + } + + log_info("spawned=%d size=%d rank=%d appnum=%d\n", spawned, size, rank, appnum); + + val = random_value(10, 100); + if (PMI_SUCCESS != (rc = PMI_Get_universe_size(&val))) { + log_fatal("PMI_Get_universe_size failed: %d\n", rc); + return rc; + } + log_assert(size == val, ""); + + val = random_value(10, 100); + if (PMI_SUCCESS != (rc = PMI_Get_id_length_max(&val))) { + log_fatal("PMI_Get_id_length_max failed: %d\n", rc); + return rc; + } + log_info("PMI_Get_id_length_max=%d\n", val); + if (!_legacy) { + log_assert(sizeof(jobid) == val, "Check PMIX_MAX_NSLEN value in pmix_common.h"); + } + + sprintf(jobid, "%s", __FUNCTION__); + if (PMI_SUCCESS != (rc = PMI_Get_id(jobid, sizeof(jobid)))) { + log_fatal("PMI_Get_id failed: %d\n", rc); + return rc; + } + + log_info("jobid=%s\n", jobid); + log_assert(memcmp(jobid, __FUNCTION__, sizeof(__FUNCTION__)), ""); + + sprintf(jobid, "%s", __FUNCTION__); + if (PMI_SUCCESS != (rc = PMI_Get_kvs_domain_id(jobid, sizeof(jobid)))) { + log_fatal("PMI_Get_kvs_domain_id failed: %d\n", rc); + return rc; + } + + log_info("PMI_Get_kvs_domain_id=%s\n", jobid); + log_assert(memcmp(jobid, __FUNCTION__, sizeof(__FUNCTION__)), ""); + + sprintf(jobid, "%s", __FUNCTION__); + if (PMI_SUCCESS != (rc = PMI_KVS_Get_my_name(jobid, sizeof(jobid)))) { + log_fatal("PMI_KVS_Get_my_name failed: %d\n", rc); + return rc; + } + + log_info("PMI_KVS_Get_my_name=%s\n", jobid); + log_assert(memcmp(jobid, __FUNCTION__, sizeof(__FUNCTION__)), ""); + + return rc; +} + +static int test_item2(void) +{ + int rc = 0; + PMI_BOOL val; + + if (PMI_SUCCESS != (rc = PMI_Initialized(&val))) { + log_fatal("PMI_Initialized failed: %d\n", rc); + return rc; + } + log_assert(PMI_TRUE == val, ""); + + return rc; +} + +static int test_item3(void) +{ + int rc = 0; + int val = 0; + + val = random_value(10, 100); + if (PMI_SUCCESS != (rc = PMI_KVS_Get_key_length_max(&val))) { + log_fatal("PMI_KVS_Get_key_length_max failed: %d\n", rc); + return rc; + } + log_info("PMI_KVS_Get_key_length_max=%d\n", val); + if (!_legacy) { + log_assert(511 == val, "Check PMIX_MAX_KEYLEN value in pmix_common.h"); + } + + val = random_value(10, 100); + if (PMI_SUCCESS != (rc = PMI_KVS_Get_value_length_max(&val))) { + log_fatal("PMI_KVS_Get_value_length_max failed: %d\n", rc); + return rc; + } + log_info("PMI_KVS_Get_value_length_max=%d\n", val); + if (!_legacy) { + log_assert(4096 == val, "Check limitation for a value"); + } + + return rc; +} + +static int test_item4(void) +{ + int rc = 0; + int val = 0; + int *ranks = NULL; + int i = 0; + + val = -1; + if (PMI_SUCCESS != (rc = PMI_Get_clique_size(&val))) { + log_fatal("PMI_Get_clique_size failed: %d\n", rc); + return rc; + } + log_info("PMI_Get_clique_size=%d\n", val); + log_assert((0 < val) && (val <= size), ""); + + ranks = alloca(val); + if (!ranks) { + return PMI_FAIL; + } + + memset(ranks, (-1), val); + if (PMI_SUCCESS != (rc = PMI_Get_clique_ranks(ranks, val))) { + log_fatal("PMI_Get_clique_ranks failed: %d\n", rc); + return rc; + } + + for (i = 0; i < val; i++) { + if (!((0 <= ranks[i]) && (ranks[i] < size))) { + log_fatal("found invalid value in ranks array: ranks[%d]=%d\n", i, ranks[i]); + return rc; + } + } + + return rc; +} + +static int test_item5(void) +{ + int rc = 0; + char *val = NULL; + int val_size = 0; + /* Predefined Job attributes */ + const char *tkeys[] = { + "PMI_process_mapping", + NULL + }; + const char **ptr = tkeys; + + if (PMI_SUCCESS != (rc = PMI_KVS_Get_value_length_max(&val_size))) { + log_fatal("PMI_KVS_Get_value_length_max failed: %d\n", rc); + return rc; + } + + val = alloca(val_size); + if (!val) { + return PMI_FAIL; + } + + while (*ptr) { + if (PMI_SUCCESS != (rc = PMI_KVS_Get(jobid, *ptr, val, val_size))) { + log_fatal("PMI_KVS_Get: [%s] %d\n", *ptr, rc); + return rc; + } + log_info("key=%s value=%.80s\n", *ptr, val); + ptr++; + } + + return rc; +} + +static int test_item6(void) +{ + int rc = 0; + char nspace[100]; + + log_error("pmix does not support this functionality\n"); + return rc; + if (0 == rank) { + if (PMI_SUCCESS != (rc = PMI_KVS_Create(nspace, sizeof(nspace)))) { + log_fatal("PMI_KVS_Create failed: %d\n", rc); + return rc; + } + log_info("nspace=%s\n", nspace); + + if (PMI_SUCCESS != (rc = PMI_KVS_Destroy(nspace))) { + log_fatal("PMI_KVS_Destroy failed: %d\n", rc); + return rc; + } + } + + return rc; +} + +static int test_item7(void) +{ + int rc = 0; + char val[100]; + const char *tkey = __FUNCTION__; + const char *tval = __FILE__; + + if (PMI_SUCCESS != (rc = PMI_KVS_Put(jobid, tkey, tval))) { + log_fatal("PMI_KVS_Put %d\n", rc); + return rc; + } + + if (PMI_SUCCESS != (rc = PMI_KVS_Get(jobid, tkey, val, sizeof(val)))) { + log_fatal("PMI_KVS_Get %d\n", rc); + return rc; + } + + log_info("tkey=%s tval=%s val=%s\n", tkey, tval, val); + + log_assert(!strcmp(tval, val), "value does not meet expectation"); + + return rc; +} + +static int test_item8(void) +{ + int rc = 0; + char tkey[100]; + char tval[100]; + char val[100]; + int i = 0; + + for (i = 0; i < size; i++) { + sprintf(tkey, "KEY-%d", i); + sprintf(tval, "VALUE-%d", i); + if (i == rank) { + if (PMI_SUCCESS != (rc = PMI_KVS_Put(jobid, tkey, tval))) { + log_fatal("PMI_KVS_Put [%s=%s] %d\n", tkey, tval, rc); + return rc; + } + } + + if (PMI_SUCCESS != (rc = PMI_KVS_Commit(jobid))) { + log_fatal("PMI_KVS_Commit %d\n", rc); + return rc; + } + + if (PMI_SUCCESS != (rc = PMI_Barrier())) { + log_fatal("PMI_Barrier %d\n", rc); + return rc; + } + + if (PMI_SUCCESS != (rc = PMI_KVS_Get(jobid, tkey, val, sizeof(val)))) { + log_fatal("PMI_KVS_Get [%s=?] %d\n", tkey, rc); + return rc; + } + + log_info("tkey=%s tval=%s val=%s\n", tkey, tval, val); + + log_assert(!strcmp(tval, val), "value does not meet expectation"); + } + return rc; } diff --git a/opal/mca/pmix/pmix1xx/pmix/test/pmix_test.c b/opal/mca/pmix/pmix1xx/pmix/test/pmix_test.c index 7e68613130..7d6ed93b44 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/pmix_test.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/pmix_test.c @@ -16,6 +16,8 @@ * Copyright (c) 2013-2015 Intel, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.c b/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.c index bb5d5a8ef7..94b9eb4c7c 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.c @@ -2,6 +2,8 @@ * Copyright (c) 2015 Intel, Inc. All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.h b/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.h index 88075f0161..8ea85ed470 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.h +++ b/opal/mca/pmix/pmix1xx/pmix/test/server_callbacks.h @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_common.c b/opal/mca/pmix/pmix1xx/pmix/test/test_common.c index 157d0b2b01..904115e175 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_common.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_common.c @@ -2,6 +2,8 @@ * Copyright (c) 2013-2015 Intel, Inc. All rights reserved. * Copyright (c) 2015 Artem Y. Polyakov . * All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_common.h b/opal/mca/pmix/pmix1xx/pmix/test/test_common.h index 85779bd8f6..8b2e19faa1 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_common.h +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_common.h @@ -4,6 +4,8 @@ * All rights reserved. * Copyright (c) 2015 Research Organization for Information Science * and Technology (RIST). All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_fence.c b/opal/mca/pmix/pmix1xx/pmix/test/test_fence.c index c33fb48dd1..226214360f 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_fence.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_fence.c @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_fence.h b/opal/mca/pmix/pmix1xx/pmix/test/test_fence.h index ef127ba651..852f4dbf1c 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_fence.h +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_fence.h @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_publish.c b/opal/mca/pmix/pmix1xx/pmix/test/test_publish.c index 17820b3d40..86f799bdea 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_publish.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_publish.c @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_publish.h b/opal/mca/pmix/pmix1xx/pmix/test/test_publish.h index 1cef663866..03295b7165 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_publish.h +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_publish.h @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.c b/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.c index 53df7c0e77..e9582cb0df 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.c @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.h b/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.h index 3060f6404d..fc402cbab0 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.h +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_resolve_peers.h @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.c b/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.c index 8b300ff1e4..3afbdc1975 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.c @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.h b/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.h index 6a26010077..2b2a12dd23 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.h +++ b/opal/mca/pmix/pmix1xx/pmix/test/test_spawn.h @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/utils.c b/opal/mca/pmix/pmix1xx/pmix/test/utils.c index f2af4325f9..ab6ad0cd05 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/utils.c +++ b/opal/mca/pmix/pmix1xx/pmix/test/utils.c @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow diff --git a/opal/mca/pmix/pmix1xx/pmix/test/utils.h b/opal/mca/pmix/pmix1xx/pmix/test/utils.h index 7d2cf0880d..bbeebaa2f7 100644 --- a/opal/mca/pmix/pmix1xx/pmix/test/utils.h +++ b/opal/mca/pmix/pmix1xx/pmix/test/utils.h @@ -1,5 +1,7 @@ /* * Copyright (c) 2015 Intel, Inc. All rights reserved. + * Copyright (c) 2015 Mellanox Technologies, Inc. + * All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow