/* KVS_Fence */ int PMI2_KVS_Fence(void) { pmix_status_t rc = PMIX_SUCCESS; PMI2_CHECK(); pmix_output_verbose(3, pmix_globals.debug_output, "PMI2_KVS_Fence"); if (PMIX_SUCCESS != (rc = PMIx_Commit())) { return convert_err(rc); } /* we want all data to be collected upon completion */ { pmix_info_t info[1]; bool val_data = 1; /* set controlling parameters * PMIX_COLLECT_DATA - meet legacy PMI2 requirement */ PMIX_INFO_CONSTRUCT(&info[0]); PMIX_INFO_LOAD(&info[0], PMIX_COLLECT_DATA, &val_data, PMIX_BOOL); rc = PMIx_Fence(NULL, 0, &info[0], 1); PMIX_INFO_DESTRUCT(&info[0]); } return convert_err(rc); }
int PMI2_Job_Spawn(int count, const char * cmds[], int argcs[], const char ** argvs[], const int maxprocs[], const int info_keyval_sizes[], const PMI_keyval_t *info_keyval_vectors[], int preput_keyval_size, const PMI_keyval_t *preput_keyval_vector[], char jobId[], int jobIdSize, int errors[]) { pmix_status_t rc = PMIX_SUCCESS; pmix_app_t *apps; int i, k; 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++) { apps[i].cmd = strdup(cmds[i]); apps[i].maxprocs = maxprocs[i]; apps[i].argv = pmix_argv_copy((char**)argvs[i]); apps[i].argc = pmix_argv_count(apps[i].argv); apps[i].ninfo = info_keyval_sizes[i]; 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++) { (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++) { (void)asprintf(&evar, "%s=%s", preput_keyval_vector[j]->key, preput_keyval_vector[j]->val); pmix_argv_append_nosize(&apps[i].env, evar); free(evar); } } rc = PMIx_Spawn(NULL, 0, apps, count, NULL); /* tear down the apps array */ for (i=0; i < count; i++) { PMIX_APP_DESTRUCT(&apps[i]); } free(apps); if (NULL != errors) { for (i=0; i < count; i++) { errors[i] = convert_err(rc); } } return convert_err(rc); }
/* KVS_Fence */ int PMI2_KVS_Fence(void) { pmix_status_t rc; 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); return convert_err(rc); }
int PMI2_Init(int *spawned, int *size, int *rank, int *appnum) { pmix_value_t *kv; pmix_status_t rc; if (PMIX_SUCCESS != PMIx_Init(&myproc)) { return PMI2_ERR_INIT; } 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); return convert_err(rc); } else { /* cannot continue without this info */ return PMI2_ERR_INIT; } } 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); return convert_err(rc); } else { /* if not found, default to not spawned */ *spawned = 0; } } 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); return convert_err(rc); } else { /* if not found, default to 0 */ *appnum = 0; } } return PMI2_SUCCESS; }
/* KVS_Put - we default to PMIX_GLOBAL scope and ignore the * provided kvsname as we only put into our own nspace */ PMIX_EXPORT int PMI_KVS_Put(const char kvsname[], const char key[], const char value[]) { 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; } if (pmi_singleton) { return PMI_SUCCESS; } pmix_output_verbose(2, pmix_globals.debug_output, "PMI_KVS_Put: KVS=%s, key=%s value=%s", kvsname, key, value); val.type = PMIX_STRING; val.data.string = (char*)value; rc = PMIx_Put(PMIX_GLOBAL, key, &val); return convert_err(rc); }
int PMI2_Finalize(void) { pmix_status_t rc; rc = PMIx_Finalize(); return convert_err(rc); }
PMIX_EXPORT int PMI_Get_clique_ranks(int ranks[], int length) { pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; char **rks; int i; pmix_proc_t proc = myproc; proc.rank = PMIX_RANK_WILDCARD; PMI_CHECK(); if (NULL == ranks) { return PMI_ERR_INVALID_ARGS; } if (pmi_singleton) { ranks[0] = 0; return PMI_SUCCESS; } rc = PMIx_Get(&proc, PMIX_LOCAL_PEERS, NULL, 0, &val); if (PMIX_SUCCESS == rc) { /* kv will contain a string of comma-separated * ranks on my node */ 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(val); } return convert_err(rc); }
PMIX_EXPORT int PMI_Publish_name(const char service_name[], const char port[]) { pmix_status_t rc = PMIX_SUCCESS; pmix_info_t info; PMI_CHECK(); if (NULL == service_name || NULL == port) { return PMI_ERR_INVALID_ARG; } if (pmi_singleton) { return PMI_FAIL; } /* pass the service/port */ (void) strncpy(info.key, service_name, PMIX_MAX_KEYLEN); info.value.type = PMIX_STRING; info.value.data.string = (char*) port; /* publish the info - PMI-1 doesn't support * any scope other than inside our own nspace */ rc = PMIx_Publish(&info, 1); return convert_err(rc); }
int PMI2_Nameserv_publish(const char service_name[], const PMI_keyval_t *info_ptr, const char port[]) { pmix_status_t rc; int nvals; pmix_info_t info[2]; 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; info[0].value.data.string = (char*)port; nvals = 1; /* if provided, add any other value */ if (NULL != info_ptr) { (void)strncpy(info[1].key, info_ptr->key, PMIX_MAX_KEYLEN); info[1].value.type = PMIX_STRING; info[1].value.data.string = (char*)info_ptr->val; nvals = 2; } /* publish the info - PMI-2 doesn't support * any scope other than inside our own nspace */ rc = PMIx_Publish(info, nvals); return convert_err(rc); }
/* KVS_Put - we default to PMIX_GLOBAL scope */ PMIX_EXPORT int PMI2_KVS_Put(const char key[], const char value[]) { pmix_status_t rc = PMIX_SUCCESS; pmix_value_t val; PMI2_CHECK(); if ((NULL == key) || (NULL == value)) { return PMI2_ERR_INVALID_ARG; } if (pmi2_singleton) { return PMI2_SUCCESS; } 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; if (PMIX_SUCCESS == (rc = PMIx_Put(PMIX_GLOBAL, key, &val))) { commit_reqd = true; } return convert_err(rc); }
/* the jobid is equated to the nspace in PMIx, and the * src_pmi_id equates to the rank. If jobid=NULL, then PMIx * will use the local nspace, which matches the PMI2 spec. * The only type of value supported by PMI2 is a string, so * the return of anything else is an error */ 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_value_t *val; pmix_proc_t proc; (void)strncpy(proc.nspace, jobid, PMIX_MAX_NSLEN); proc.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); } return convert_err(rc); }
int PMI2_Info_GetSize(int *size) { pmix_status_t rc = PMIX_ERROR; pmix_value_t *val; pmix_info_t info[1]; bool val_optinal = 1; PMI2_CHECK(); if (NULL == size) { return PMI2_ERR_INVALID_ARGS; } /* set controlling parameters * PMIX_OPTIONAL - expect that these keys should be available on startup */ PMIX_INFO_CONSTRUCT(&info[0]); PMIX_INFO_LOAD(&info[0], PMIX_OPTIONAL, &val_optinal, PMIX_BOOL); if (PMIX_SUCCESS == PMIx_Get(&myproc, PMIX_LOCAL_SIZE, info, 1, &val)) { rc = convert_int(size, val); PMIX_VALUE_RELEASE(val); } PMIX_INFO_DESTRUCT(&info[0]); return convert_err(rc); }
int PMI2_Nameserv_unpublish(const char service_name[], const PMI_keyval_t *info_ptr) { pmix_status_t rc = PMIX_SUCCESS; char *keys[3]; PMI2_CHECK(); if (NULL == service_name || NULL == info_ptr) { return PMI2_ERR_INVALID_ARG; } /* pass the service */ keys[0] = (char*)service_name; keys[1] = NULL; keys[2] = NULL; /* if provided, add any other value */ if (NULL != info_ptr) { keys[1] = info_ptr->key; } rc = PMIx_Unpublish(keys, NULL, 0); return convert_err(rc); }
int PMI2_Abort(int flag, const char msg[]) { pmix_status_t rc; rc = PMIx_Abort(flag, msg, NULL, 0); return convert_err(rc); }
PMIX_EXPORT int PMI2_Nameserv_lookup(const char service_name[], const PMI_keyval_t *info_ptr, char port[], int portLen) { 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; } if (pmi2_singleton) { return PMI2_FAIL; } PMIX_PDATA_CONSTRUCT(&pdata[0]); PMIX_PDATA_CONSTRUCT(&pdata[1]); /* pass the service */ (void)strncpy(pdata[0].key, service_name, PMIX_MAX_KEYLEN); nvals = 1; /* if provided, add any other value */ if (NULL != info_ptr) { (void)strncpy(pdata[1].key, info_ptr->key, PMIX_MAX_KEYLEN); pdata[1].value.type = PMIX_STRING; pdata[1].value.data.string = info_ptr->val; nvals = 2; } /* lookup the info */ if (PMIX_SUCCESS != (rc = PMIx_Lookup(pdata, nvals, NULL, 0))) { PMIX_PDATA_DESTRUCT(&pdata[0]); PMIX_PDATA_DESTRUCT(&pdata[1]); return convert_err(rc); } /* should have received a string back */ if (PMIX_STRING != pdata[0].value.type || NULL == pdata[0].value.data.string) { PMIX_PDATA_DESTRUCT(&pdata[0]); PMIX_PDATA_DESTRUCT(&pdata[1]); return PMI2_FAIL; } /* return the port */ (void)strncpy(port, pdata[0].value.data.string, portLen); PMIX_PDATA_DESTRUCT(&pdata[0]); if (NULL != info_ptr) { } PMIX_PDATA_DESTRUCT(&pdata[1]); return PMI2_SUCCESS; }
PMIX_EXPORT int PMI_Init(int *spawned) { pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; pmix_proc_t proc; pmix_info_t info[1]; bool val_optinal = 1; if (PMIX_SUCCESS != (rc = PMIx_Init(&myproc, NULL, 0))) { /* if we didn't see a PMIx server (e.g., missing envar), * then allow us to run as a singleton */ if (PMIX_ERR_INVALID_NAMESPACE == rc) { if (NULL != spawned) { *spawned = 0; } pmi_singleton = true; (void)strncpy(myproc.nspace, "1234", PMIX_MAX_NSLEN); myproc.rank = 0; pmi_init = 1; return PMI_SUCCESS; } return PMI_ERR_INIT; } /* getting internal key requires special rank value */ memcpy(&proc, &myproc, sizeof(myproc)); proc.rank = PMIX_RANK_UNDEF; /* set controlling parameters * PMIX_OPTIONAL - expect that these keys should be available on startup */ PMIX_INFO_CONSTRUCT(&info[0]); PMIX_INFO_LOAD(&info[0], PMIX_OPTIONAL, &val_optinal, PMIX_BOOL); if (NULL != spawned) { /* get the spawned flag */ if (PMIX_SUCCESS == PMIx_Get(&proc, PMIX_SPAWNED, info, 1, &val)) { rc = convert_int(spawned, val); PMIX_VALUE_RELEASE(val); if (PMIX_SUCCESS != rc) { goto error; } } else { /* if not found, default to not spawned */ *spawned = 0; } } pmi_init = 1; rc = PMIX_SUCCESS; error: PMIX_INFO_DESTRUCT(&info[0]); return convert_err(rc); }
/* KVS_Put - we default to PMIX_GLOBAL scope */ int PMI2_KVS_Put(const char key[], const char value[]) { pmix_status_t rc; pmix_value_t val; val.type = PMIX_STRING; val.data.string = (char*)value; rc = PMIx_Put(PMIX_GLOBAL, key, &val); return convert_err(rc); }
/* push info at the PMIX_LOCAL scope */ int PMI2_Info_PutNodeAttr(const char name[], const char value[]) { pmix_status_t rc; pmix_value_t val; val.type = PMIX_STRING; val.data.string = (char*)value; rc = PMIx_Put(PMIX_LOCAL, name, &val); return convert_err(rc); }
int PMI2_Job_Disconnect(const char jobid[]) { pmix_status_t rc; pmix_proc_t proc; (void)strncpy(proc.nspace, jobid, PMIX_MAX_NSLEN); proc.rank = PMIX_RANK_WILDCARD; rc = PMIx_Disconnect(&proc, 1, NULL, 0); return convert_err(rc); }
int PMI2_Finalize(void) { pmix_status_t rc = PMIX_SUCCESS; PMI2_CHECK(); pmi2_init = 0; rc = PMIx_Finalize(); return convert_err(rc); }
int PMI2_Job_Disconnect(const char jobid[]) { pmix_status_t rc = PMIX_SUCCESS; pmix_proc_t proc; PMI2_CHECK(); (void)strncpy(proc.nspace, (jobid ? jobid : myproc.nspace), sizeof(myproc.nspace)); proc.rank = PMIX_RANK_WILDCARD; rc = PMIx_Disconnect(&proc, 1, NULL, 0); return convert_err(rc); }
PMIX_EXPORT int PMI_Lookup_name(const char service_name[], char port[]) { pmix_status_t rc = PMIX_SUCCESS; pmix_pdata_t pdata; PMI_CHECK(); if (NULL == service_name || NULL == port) { return PMI_ERR_INVALID_ARG; } if (pmi_singleton) { return PMI_FAIL; } PMIX_PDATA_CONSTRUCT(&pdata); /* pass the service */ (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))) { return convert_err(rc); } /* should have received a string back */ if (PMIX_STRING != pdata.value.type || NULL == pdata.value.data.string) { return convert_err(PMIX_ERR_NOT_FOUND); } /* return the port - sadly, this API doesn't tell us * the size of the port array, and so there is a * 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); PMIX_PDATA_DESTRUCT(&pdata); return PMIX_SUCCESS; }
PMIX_EXPORT int PMI_Abort(int flag, const char msg[]) { pmix_status_t rc = PMIX_SUCCESS; PMI_CHECK(); if (pmi_singleton) { return PMI_SUCCESS; } rc = PMIx_Abort(flag, msg, NULL, 0); return convert_err(rc); }
PMIX_EXPORT int PMI_Finalize(void) { pmix_status_t rc = PMIX_SUCCESS; PMI_CHECK(); if (pmi_singleton) { return PMI_SUCCESS; } pmi_init = 0; rc = PMIx_Finalize(NULL, 0); return convert_err(rc); }
/* push info at the PMIX_LOCAL scope */ int PMI2_Info_PutNodeAttr(const char name[], const char value[]) { 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); return convert_err(rc); }
int PMI2_Job_Connect(const char jobid[], PMI2_Connect_comm_t *conn) { pmix_status_t rc = PMIX_SUCCESS; pmix_proc_t proc; PMI2_CHECK(); if (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); return convert_err(rc); }
PMIX_EXPORT int PMI2_Job_Disconnect(const char jobid[]) { pmix_status_t rc = PMIX_SUCCESS; pmix_proc_t proc; PMI2_CHECK(); if (pmi2_singleton) { return PMI2_SUCCESS; } memset(proc.nspace, 0, sizeof(proc.nspace)); (void)strncpy(proc.nspace, (jobid ? jobid : proc.nspace), sizeof(proc.nspace)-1); proc.rank = PMIX_RANK_WILDCARD; rc = PMIx_Disconnect(&proc, 1, NULL, 0); return convert_err(rc); }
PMIX_EXPORT int PMI2_Info_GetNodeAttr(const char name[], char value[], int valuelen, int *found, int waitfor) { pmix_status_t rc = PMIX_SUCCESS; pmix_value_t *val; pmix_info_t info[1]; bool val_optinal = 1; pmix_proc_t proc = myproc; proc.rank = PMIX_RANK_UNDEF; PMI2_CHECK(); if ((NULL == name) || (NULL == value) || (NULL == found)) { return PMI2_ERR_INVALID_ARG; } if (pmi2_singleton) { return PMI2_FAIL; } /* set controlling parameters * PMIX_OPTIONAL - expect that these keys should be available on startup */ PMIX_INFO_CONSTRUCT(&info[0]); PMIX_INFO_LOAD(&info[0], PMIX_OPTIONAL, &val_optinal, PMIX_BOOL); *found = 0; /* TODO: does PMI2's "name" makes sense to PMIx? */ rc = PMIx_Get(&proc, name, info, 1, &val); if (PMIX_SUCCESS == rc && NULL != val) { if (PMIX_STRING != val->type) { rc = PMIX_ERROR; } else if (NULL != val->data.string) { (void)strncpy(value, val->data.string, valuelen); *found = 1; } PMIX_VALUE_RELEASE(val); } else if (PMIX_ERR_NOT_FOUND == rc) { rc = PMIX_SUCCESS; } PMIX_INFO_DESTRUCT(&info[0]); return convert_err(rc); }
/* the jobid is equated to the nspace in PMIx, and the * src_pmi_id equates to the rank. If jobid=NULL, then PMIx * will use the local nspace, which matches the PMI2 spec. * The only type of value supported by PMI2 is a string, so * the return of anything else is an error */ PMIX_EXPORT 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_SUCCESS; pmix_value_t *val; pmix_proc_t proc; PMI2_CHECK(); if (commit_reqd) { /* they didn't commit after a put */ return PMI2_FAIL; } /* set default */ *vallen = 0; 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) { /* the rank is UNDEF */ proc.rank = PMIX_RANK_UNDEF; } else { proc.rank = src_pmi_id; } rc = PMIx_Get(&proc, key, NULL, 0, &val); if (PMIX_SUCCESS == rc && NULL != val) { if (PMIX_STRING != val->type) { rc = PMIX_ERROR; } else if (NULL != val->data.string) { (void)strncpy(value, val->data.string, maxvalue); *vallen = strlen(val->data.string); } PMIX_VALUE_RELEASE(val); } return convert_err(rc); }
int PMI2_Nameserv_unpublish(const char service_name[], const PMI_keyval_t *info_ptr) { char *keys[3]; pmix_status_t rc; /* pass the service */ keys[0] = (char*)service_name; keys[1] = NULL; keys[2] = NULL; /* if provided, add any other value */ if (NULL != info_ptr) { keys[1] = info_ptr->key; } rc = PMIx_Unpublish(keys, NULL, 0); return convert_err(rc); }