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); }
int pmix_bfrop_copy_app(pmix_app_t **dest, pmix_app_t *src, pmix_data_type_t type) { size_t j; *dest = (pmix_app_t*)malloc(sizeof(pmix_app_t)); (*dest)->cmd = strdup(src->cmd); (*dest)->argc = src->argc; (*dest)->argv = pmix_argv_copy(src->argv); (*dest)->env = pmix_argv_copy(src->env); (*dest)->maxprocs = src->maxprocs; (*dest)->ninfo = src->ninfo; (*dest)->info = (pmix_info_t*)malloc(src->ninfo * sizeof(pmix_info_t)); for (j=0; j < src->ninfo; j++) { (void)strncpy((*dest)->info[j].key, src->info[j].key, PMIX_MAX_KEYLEN); pmix_value_xfer(&(*dest)->info[j].value, &src->info[j].value); } return PMIX_SUCCESS; }
/* Xfer FUNCTIONS FOR GENERIC PMIX TYPES */ pmix_status_t pmix_bfrops_base_value_xfer(pmix_value_t *p, pmix_value_t *src) { size_t n, m; pmix_status_t rc; char **prarray, **strarray; pmix_value_t *pv, *sv; pmix_info_t *p1, *s1; pmix_app_t *pa, *sa; pmix_pdata_t *pd, *sd; pmix_buffer_t *pb, *sb; pmix_byte_object_t *pbo, *sbo; pmix_kval_t *pk, *sk; pmix_modex_data_t *pm, *sm; pmix_proc_info_t *pi, *si; pmix_query_t *pq, *sq; pmix_envar_t *pe, *se; /* copy the right field */ p->type = src->type; switch (src->type) { case PMIX_UNDEF: break; case PMIX_BOOL: p->data.flag = src->data.flag; break; case PMIX_BYTE: p->data.byte = src->data.byte; break; case PMIX_STRING: if (NULL != src->data.string) { p->data.string = strdup(src->data.string); } else { p->data.string = NULL; } break; case PMIX_SIZE: p->data.size = src->data.size; break; case PMIX_PID: p->data.pid = src->data.pid; break; case PMIX_INT: /* to avoid alignment issues */ memcpy(&p->data.integer, &src->data.integer, sizeof(int)); break; case PMIX_INT8: p->data.int8 = src->data.int8; break; case PMIX_INT16: /* to avoid alignment issues */ memcpy(&p->data.int16, &src->data.int16, 2); break; case PMIX_INT32: /* to avoid alignment issues */ memcpy(&p->data.int32, &src->data.int32, 4); break; case PMIX_INT64: /* to avoid alignment issues */ memcpy(&p->data.int64, &src->data.int64, 8); break; case PMIX_UINT: /* to avoid alignment issues */ memcpy(&p->data.uint, &src->data.uint, sizeof(unsigned int)); break; case PMIX_UINT8: p->data.uint8 = src->data.uint8; break; case PMIX_UINT16: /* to avoid alignment issues */ memcpy(&p->data.uint16, &src->data.uint16, 2); break; case PMIX_UINT32: /* to avoid alignment issues */ memcpy(&p->data.uint32, &src->data.uint32, 4); break; case PMIX_UINT64: /* to avoid alignment issues */ memcpy(&p->data.uint64, &src->data.uint64, 8); break; case PMIX_FLOAT: p->data.fval = src->data.fval; break; case PMIX_DOUBLE: p->data.dval = src->data.dval; break; case PMIX_TIMEVAL: memcpy(&p->data.tv, &src->data.tv, sizeof(struct timeval)); break; case PMIX_TIME: memcpy(&p->data.time, &src->data.time, sizeof(time_t)); break; case PMIX_STATUS: memcpy(&p->data.status, &src->data.status, sizeof(pmix_status_t)); break; case PMIX_PROC: PMIX_PROC_CREATE(p->data.proc, 1); if (NULL == p->data.proc) { return PMIX_ERR_NOMEM; } memcpy(p->data.proc, src->data.proc, sizeof(pmix_proc_t)); break; case PMIX_PROC_RANK: memcpy(&p->data.rank, &src->data.rank, sizeof(pmix_rank_t)); break; case PMIX_BYTE_OBJECT: case PMIX_COMPRESSED_STRING: memset(&p->data.bo, 0, sizeof(pmix_byte_object_t)); if (NULL != src->data.bo.bytes && 0 < src->data.bo.size) { p->data.bo.bytes = malloc(src->data.bo.size); memcpy(p->data.bo.bytes, src->data.bo.bytes, src->data.bo.size); p->data.bo.size = src->data.bo.size; } else { p->data.bo.bytes = NULL; p->data.bo.size = 0; } break; case PMIX_PERSIST: memcpy(&p->data.persist, &src->data.persist, sizeof(pmix_persistence_t)); break; case PMIX_SCOPE: memcpy(&p->data.scope, &src->data.scope, sizeof(pmix_scope_t)); break; case PMIX_DATA_RANGE: memcpy(&p->data.range, &src->data.range, sizeof(pmix_data_range_t)); break; case PMIX_PROC_STATE: memcpy(&p->data.state, &src->data.state, sizeof(pmix_proc_state_t)); break; case PMIX_PROC_INFO: PMIX_PROC_INFO_CREATE(p->data.pinfo, 1); if (NULL != src->data.pinfo->hostname) { p->data.pinfo->hostname = strdup(src->data.pinfo->hostname); } if (NULL != src->data.pinfo->executable_name) { p->data.pinfo->executable_name = strdup(src->data.pinfo->executable_name); } memcpy(&p->data.pinfo->pid, &src->data.pinfo->pid, sizeof(pid_t)); memcpy(&p->data.pinfo->exit_code, &src->data.pinfo->exit_code, sizeof(int)); memcpy(&p->data.pinfo->state, &src->data.pinfo->state, sizeof(pmix_proc_state_t)); break; case PMIX_DATA_ARRAY: p->data.darray = (pmix_data_array_t*)calloc(1, sizeof(pmix_data_array_t)); p->data.darray->type = src->data.darray->type; p->data.darray->size = src->data.darray->size; if (0 == p->data.darray->size || NULL == src->data.darray->array) { p->data.darray->array = NULL; p->data.darray->size = 0; break; } /* allocate space and do the copy */ switch (src->data.darray->type) { case PMIX_UINT8: case PMIX_INT8: case PMIX_BYTE: p->data.darray->array = (char*)malloc(src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size); break; case PMIX_UINT16: case PMIX_INT16: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(uint16_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(uint16_t)); break; case PMIX_UINT32: case PMIX_INT32: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(uint32_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(uint32_t)); break; case PMIX_UINT64: case PMIX_INT64: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(uint64_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(uint64_t)); break; case PMIX_BOOL: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(bool)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(bool)); break; case PMIX_SIZE: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(size_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(size_t)); break; case PMIX_PID: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(pid_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pid_t)); break; case PMIX_STRING: p->data.darray->array = (char**)malloc(src->data.darray->size * sizeof(char*)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } prarray = (char**)p->data.darray->array; strarray = (char**)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { if (NULL != strarray[n]) { prarray[n] = strdup(strarray[n]); } } break; case PMIX_INT: case PMIX_UINT: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(int)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(int)); break; case PMIX_FLOAT: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(float)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(float)); break; case PMIX_DOUBLE: p->data.darray->array = (char*)malloc(src->data.darray->size * sizeof(double)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(double)); break; case PMIX_TIMEVAL: p->data.darray->array = (struct timeval*)malloc(src->data.darray->size * sizeof(struct timeval)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(struct timeval)); break; case PMIX_TIME: p->data.darray->array = (time_t*)malloc(src->data.darray->size * sizeof(time_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(time_t)); break; case PMIX_STATUS: p->data.darray->array = (pmix_status_t*)malloc(src->data.darray->size * sizeof(pmix_status_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_status_t)); break; case PMIX_VALUE: PMIX_VALUE_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pv = (pmix_value_t*)p->data.darray->array; sv = (pmix_value_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { if (PMIX_SUCCESS != (rc = pmix_value_xfer(&pv[n], &sv[n]))) { PMIX_VALUE_FREE(pv, src->data.darray->size); return rc; } } break; case PMIX_PROC: PMIX_PROC_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_proc_t)); break; case PMIX_APP: PMIX_APP_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pa = (pmix_app_t*)p->data.darray->array; sa = (pmix_app_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { if (NULL != sa[n].cmd) { pa[n].cmd = strdup(sa[n].cmd); } if (NULL != sa[n].argv) { pa[n].argv = pmix_argv_copy(sa[n].argv); } if (NULL != sa[n].env) { pa[n].env = pmix_argv_copy(sa[n].env); } if (NULL != sa[n].cwd) { pa[n].cwd = strdup(sa[n].cwd); } pa[n].maxprocs = sa[n].maxprocs; if (0 < sa[n].ninfo && NULL != sa[n].info) { PMIX_INFO_CREATE(pa[n].info, sa[n].ninfo); if (NULL == pa[n].info) { PMIX_APP_FREE(pa, src->data.darray->size); return PMIX_ERR_NOMEM; } pa[n].ninfo = sa[n].ninfo; for (m=0; m < pa[n].ninfo; m++) { PMIX_INFO_XFER(&pa[n].info[m], &sa[n].info[m]); } } } break; case PMIX_INFO: PMIX_INFO_CREATE(p->data.darray->array, src->data.darray->size); p1 = (pmix_info_t*)p->data.darray->array; s1 = (pmix_info_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { PMIX_INFO_XFER(&p1[n], &s1[n]); } break; case PMIX_PDATA: PMIX_PDATA_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pd = (pmix_pdata_t*)p->data.darray->array; sd = (pmix_pdata_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { PMIX_PDATA_XFER(&pd[n], &sd[n]); } break; case PMIX_BUFFER: p->data.darray->array = (pmix_buffer_t*)malloc(src->data.darray->size * sizeof(pmix_buffer_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pb = (pmix_buffer_t*)p->data.darray->array; sb = (pmix_buffer_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { PMIX_CONSTRUCT(&pb[n], pmix_buffer_t); pmix_bfrops_base_copy_payload(&pb[n], &sb[n]); } break; case PMIX_BYTE_OBJECT: case PMIX_COMPRESSED_STRING: p->data.darray->array = (pmix_byte_object_t*)malloc(src->data.darray->size * sizeof(pmix_byte_object_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pbo = (pmix_byte_object_t*)p->data.darray->array; sbo = (pmix_byte_object_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { if (NULL != sbo[n].bytes && 0 < sbo[n].size) { pbo[n].size = sbo[n].size; pbo[n].bytes = (char*)malloc(pbo[n].size); memcpy(pbo[n].bytes, sbo[n].bytes, pbo[n].size); } else { pbo[n].bytes = NULL; pbo[n].size = 0; } } break; case PMIX_KVAL: p->data.darray->array = (pmix_kval_t*)calloc(src->data.darray->size , sizeof(pmix_kval_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pk = (pmix_kval_t*)p->data.darray->array; sk = (pmix_kval_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { if (NULL != sk[n].key) { pk[n].key = strdup(sk[n].key); } if (NULL != sk[n].value) { PMIX_VALUE_CREATE(pk[n].value, 1); if (NULL == pk[n].value) { free(p->data.darray->array); return PMIX_ERR_NOMEM; } if (PMIX_SUCCESS != (rc = pmix_value_xfer(pk[n].value, sk[n].value))) { return rc; } } } break; case PMIX_MODEX: PMIX_MODEX_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pm = (pmix_modex_data_t*)p->data.darray->array; sm = (pmix_modex_data_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { memcpy(&pm[n], &sm[n], sizeof(pmix_modex_data_t)); if (NULL != sm[n].blob && 0 < sm[n].size) { pm[n].blob = (uint8_t*)malloc(sm[n].size); if (NULL == pm[n].blob) { return PMIX_ERR_NOMEM; } memcpy(pm[n].blob, sm[n].blob, sm[n].size); pm[n].size = sm[n].size; } else { pm[n].blob = NULL; pm[n].size = 0; } } break; case PMIX_PERSIST: p->data.darray->array = (pmix_persistence_t*)malloc(src->data.darray->size * sizeof(pmix_persistence_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_persistence_t)); break; case PMIX_POINTER: p->data.darray->array = (char**)malloc(src->data.darray->size * sizeof(char*)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } prarray = (char**)p->data.darray->array; strarray = (char**)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { prarray[n] = strarray[n]; } break; case PMIX_SCOPE: p->data.darray->array = (pmix_scope_t*)malloc(src->data.darray->size * sizeof(pmix_scope_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_scope_t)); break; case PMIX_DATA_RANGE: p->data.darray->array = (pmix_data_range_t*)malloc(src->data.darray->size * sizeof(pmix_data_range_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_data_range_t)); break; case PMIX_COMMAND: p->data.darray->array = (pmix_cmd_t*)malloc(src->data.darray->size * sizeof(pmix_cmd_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_cmd_t)); break; case PMIX_INFO_DIRECTIVES: p->data.darray->array = (pmix_info_directives_t*)malloc(src->data.darray->size * sizeof(pmix_info_directives_t)); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } memcpy(p->data.darray->array, src->data.darray->array, src->data.darray->size * sizeof(pmix_info_directives_t)); break; case PMIX_PROC_INFO: PMIX_PROC_INFO_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pi = (pmix_proc_info_t*)p->data.darray->array; si = (pmix_proc_info_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { memcpy(&pi[n].proc, &si[n].proc, sizeof(pmix_proc_t)); if (NULL != si[n].hostname) { pi[n].hostname = strdup(si[n].hostname); } else { pi[n].hostname = NULL; } if (NULL != si[n].executable_name) { pi[n].executable_name = strdup(si[n].executable_name); } else { pi[n].executable_name = NULL; } pi[n].pid = si[n].pid; pi[n].exit_code = si[n].exit_code; pi[n].state = si[n].state; } break; case PMIX_DATA_ARRAY: PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED); return PMIX_ERR_NOT_SUPPORTED; // don't support iterative arrays case PMIX_QUERY: PMIX_QUERY_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pq = (pmix_query_t*)p->data.darray->array; sq = (pmix_query_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { if (NULL != sq[n].keys) { pq[n].keys = pmix_argv_copy(sq[n].keys); } if (NULL != sq[n].qualifiers && 0 < sq[n].nqual) { PMIX_INFO_CREATE(pq[n].qualifiers, sq[n].nqual); if (NULL == pq[n].qualifiers) { PMIX_QUERY_FREE(pq, src->data.darray->size); return PMIX_ERR_NOMEM; } for (m=0; m < sq[n].nqual; m++) { PMIX_INFO_XFER(&pq[n].qualifiers[m], &sq[n].qualifiers[m]); } pq[n].nqual = sq[n].nqual; } else { pq[n].qualifiers = NULL; pq[n].nqual = 0; } } break; case PMIX_ENVAR: PMIX_ENVAR_CREATE(p->data.darray->array, src->data.darray->size); if (NULL == p->data.darray->array) { return PMIX_ERR_NOMEM; } pe = (pmix_envar_t*)p->data.darray->array; se = (pmix_envar_t*)src->data.darray->array; for (n=0; n < src->data.darray->size; n++) { if (NULL != se[n].envar) { pe[n].envar = strdup(se[n].envar); } if (NULL != se[n].value) { pe[n].value = strdup(se[n].value); } pe[n].separator = se[n].separator; } break; default: return PMIX_ERR_UNKNOWN_DATA_TYPE; } break; case PMIX_POINTER: memcpy(&p->data.ptr, &src->data.ptr, sizeof(void*)); break; case PMIX_ENVAR: PMIX_ENVAR_CONSTRUCT(&p->data.envar); if (NULL != src->data.envar.envar) { p->data.envar.envar = strdup(src->data.envar.envar); } if (NULL != src->data.envar.value) { p->data.envar.value = strdup(src->data.envar.value); } p->data.envar.separator = src->data.envar.separator; break; /**** DEPRECATED ****/ case PMIX_INFO_ARRAY: p->data.array->size = src->data.array->size; if (0 < src->data.array->size) { p->data.array->array = (pmix_info_t*)malloc(src->data.array->size * sizeof(pmix_info_t)); if (NULL == p->data.array->array) { return PMIX_ERR_NOMEM; } p1 = (pmix_info_t*)p->data.array->array; s1 = (pmix_info_t*)src->data.array->array; for (n=0; n < src->data.darray->size; n++) { PMIX_INFO_XFER(&p1[n], &s1[n]); } } break; /********************/ default: pmix_output(0, "XFER-PMIX-VALUE: UNSUPPORTED TYPE %d", (int)src->type); assert(0); return PMIX_ERROR; } return PMIX_SUCCESS; }
int main(int argc, char **argv) { char **client_env=NULL; char **client_argv=NULL; int rc; struct stat stat_buf; struct timeval tv; double test_start; cli_state_t order[CLI_TERM+1]; test_params params; INIT_TEST_PARAMS(params); int test_fail = 0; char *tmp; int ns_nprocs; gettimeofday(&tv, NULL); test_start = tv.tv_sec + 1E-6*tv.tv_usec; /* smoke test */ if (PMIX_SUCCESS != 0) { TEST_ERROR(("ERROR IN COMPUTING CONSTANTS: PMIX_SUCCESS = %d", PMIX_SUCCESS)); exit(1); } TEST_VERBOSE(("Testing version %s", PMIx_Get_version())); parse_cmd(argc, argv, ¶ms); TEST_VERBOSE(("Start PMIx_lite smoke test (timeout is %d)", params.timeout)); /* verify executable */ if( 0 > ( rc = stat(params.binary, &stat_buf) ) ){ TEST_ERROR(("Cannot stat() executable \"%s\": %d: %s", params.binary, errno, strerror(errno))); FREE_TEST_PARAMS(params); return 0; } else if( !S_ISREG(stat_buf.st_mode) ){ TEST_ERROR(("Client executable \"%s\": is not a regular file", params.binary)); FREE_TEST_PARAMS(params); return 0; }else if( !(stat_buf.st_mode & S_IXUSR) ){ TEST_ERROR(("Client executable \"%s\": has no executable flag", params.binary)); FREE_TEST_PARAMS(params); return 0; } /* setup the server library */ pmix_info_t info[1]; (void)strncpy(info[0].key, PMIX_SOCKET_MODE, PMIX_MAX_KEYLEN); info[0].value.type = PMIX_UINT32; info[0].value.data.uint32 = 0666; if (PMIX_SUCCESS != (rc = PMIx_server_init(&mymodule, info, 1))) { TEST_ERROR(("Init failed with error %d", rc)); FREE_TEST_PARAMS(params); return rc; } /* register the errhandler */ PMIx_Register_event_handler(NULL, 0, NULL, 0, errhandler, errhandler_reg_callbk, NULL); order[CLI_UNINIT] = CLI_FORKED; order[CLI_FORKED] = CLI_FIN; order[CLI_CONNECTED] = CLI_UNDEF; order[CLI_FIN] = CLI_TERM; order[CLI_DISCONN] = CLI_UNDEF; order[CLI_TERM] = CLI_UNDEF; cli_init(params.nprocs, order); /* set common argv and env */ client_env = pmix_argv_copy(environ); set_client_argv(¶ms, &client_argv); tmp = pmix_argv_join(client_argv, ' '); TEST_VERBOSE(("Executing test: %s", tmp)); free(tmp); int launched = 0; /* set namespaces and fork clients */ if (NULL == params.ns_dist) { /* we have a single namespace for all clients */ ns_nprocs = params.nprocs; rc = launch_clients(ns_nprocs, params.binary, &client_env, &client_argv); if (PMIX_SUCCESS != rc) { FREE_TEST_PARAMS(params); return rc; } launched += ns_nprocs; } else { char *pch; pch = strtok(params.ns_dist, ":"); while (NULL != pch) { ns_nprocs = (int)strtol(pch, NULL, 10); if (params.nprocs < (uint32_t)(launched+ns_nprocs)) { TEST_ERROR(("Total number of processes doesn't correspond number specified by ns_dist parameter.")); FREE_TEST_PARAMS(params); return PMIX_ERROR; } if (0 < ns_nprocs) { rc = launch_clients(ns_nprocs, params.binary, &client_env, &client_argv); if (PMIX_SUCCESS != rc) { FREE_TEST_PARAMS(params); return rc; } } pch = strtok (NULL, ":"); launched += ns_nprocs; } } if (params.nprocs != (uint32_t)launched) { TEST_ERROR(("Total number of processes doesn't correspond number specified by ns_dist parameter.")); cli_kill_all(); test_fail = 1; } /* hang around until the client(s) finalize */ while (!test_terminated()) { // To avoid test hang we want to interrupt the loop each 0.1s double test_current; // check if we exceed the max time gettimeofday(&tv, NULL); test_current = tv.tv_sec + 1E-6*tv.tv_usec; if( (test_current - test_start) > params.timeout ){ break; } cli_wait_all(0); } if( !test_terminated() ){ TEST_ERROR(("Test exited by a timeout!")); cli_kill_all(); test_fail = 1; } if( test_abort ){ TEST_ERROR(("Test was aborted!")); /* do not simply kill the clients as that generates * event notifications which these tests then print * out, flooding the log */ // cli_kill_all(); test_fail = 1; } if (0 != params.test_spawn) { PMIX_WAIT_FOR_COMPLETION(spawn_wait); } pmix_argv_free(client_argv); pmix_argv_free(client_env); /* deregister the errhandler */ PMIx_Deregister_event_handler(0, op_callbk, NULL); cli_wait_all(1.0); /* finalize the server library */ if (PMIX_SUCCESS != (rc = PMIx_server_finalize())) { TEST_ERROR(("Finalize failed with error %d", rc)); } FREE_TEST_PARAMS(params); if (0 == test_fail) { TEST_OUTPUT(("Test finished OK!")); } return test_fail; }
int launch_clients(int num_procs, char *binary, char *** client_env, char ***base_argv) { int n; uid_t myuid; gid_t mygid; char *ranks = NULL; char digit[MAX_DIGIT_LEN]; int rc; static int counter = 0; static int num_ns = 0; pmix_proc_t proc; TEST_VERBOSE(("Setting job info")); fill_seq_ranks_array(num_procs, counter, &ranks); if (NULL == ranks) { PMIx_server_finalize(); TEST_ERROR(("fill_seq_ranks_array failed")); return PMIX_ERROR; } (void)snprintf(proc.nspace, PMIX_MAX_NSLEN, "%s-%d", TEST_NAMESPACE, num_ns); set_namespace(num_procs, ranks, proc.nspace); if (NULL != ranks) { free(ranks); } myuid = getuid(); mygid = getgid(); /* fork/exec the test */ for (n = 0; n < num_procs; n++) { proc.rank = counter; if (PMIX_SUCCESS != (rc = PMIx_server_setup_fork(&proc, client_env))) {//n TEST_ERROR(("Server fork setup failed with error %d", rc)); PMIx_server_finalize(); cli_kill_all(); return rc; } if (PMIX_SUCCESS != (rc = PMIx_server_register_client(&proc, myuid, mygid, NULL, NULL, NULL))) {//n TEST_ERROR(("Server fork setup failed with error %d", rc)); PMIx_server_finalize(); cli_kill_all(); return rc; } cli_info[counter].pid = fork(); if (cli_info[counter].pid < 0) { TEST_ERROR(("Fork failed")); PMIx_server_finalize(); cli_kill_all(); return -1; } cli_info[counter].rank = counter;//n cli_info[counter].ns = strdup(proc.nspace); char **client_argv = pmix_argv_copy(*base_argv); /* add two last arguments: -r <rank> */ sprintf(digit, "%d", counter);//n pmix_argv_append_nosize(&client_argv, "-r"); pmix_argv_append_nosize(&client_argv, digit); pmix_argv_append_nosize(&client_argv, "-s"); pmix_argv_append_nosize(&client_argv, proc.nspace); sprintf(digit, "%d", num_procs); pmix_argv_append_nosize(&client_argv, "--ns-size"); pmix_argv_append_nosize(&client_argv, digit); sprintf(digit, "%d", num_ns); pmix_argv_append_nosize(&client_argv, "--ns-id"); pmix_argv_append_nosize(&client_argv, digit); sprintf(digit, "%d", (counter-n)); pmix_argv_append_nosize(&client_argv, "--base-rank"); pmix_argv_append_nosize(&client_argv, digit); if (cli_info[counter].pid == 0) { if( !TEST_VERBOSE_GET() ){ // Hide clients stdout // TODO: on some systems stdout is a constant, address this fclose(stdout); stdout = fopen("/dev/null","w"); } execve(binary, client_argv, *client_env); /* Does not return */ exit(0); } cli_info[counter].state = CLI_FORKED; pmix_argv_free(client_argv); counter++; } num_ns++; return PMIX_SUCCESS; }
int main(int argc, char **argv) { char **client_env=NULL; char **client_argv=NULL; int rc; struct stat stat_buf; struct timeval tv; double test_start; test_params params; INIT_TEST_PARAMS(params); int test_fail = 0; char *tmp; int ns_nprocs; gettimeofday(&tv, NULL); test_start = tv.tv_sec + 1E-6*tv.tv_usec; /* smoke test */ if (PMIX_SUCCESS != 0) { TEST_ERROR(("ERROR IN COMPUTING CONSTANTS: PMIX_SUCCESS = %d", PMIX_SUCCESS)); exit(1); } TEST_VERBOSE(("Testing version %s", PMIx_Get_version())); parse_cmd(argc, argv, ¶ms); TEST_VERBOSE(("Start PMIx_lite smoke test (timeout is %d)", params.timeout)); /* set common argv and env */ client_env = pmix_argv_copy(environ); set_client_argv(¶ms, &client_argv); tmp = pmix_argv_join(client_argv, ' '); TEST_VERBOSE(("Executing test: %s", tmp)); free(tmp); /* verify executable */ if( 0 > ( rc = stat(params.binary, &stat_buf) ) ){ TEST_ERROR(("Cannot stat() executable \"%s\": %d: %s", params.binary, errno, strerror(errno))); FREE_TEST_PARAMS(params); return 0; } else if( !S_ISREG(stat_buf.st_mode) ){ TEST_ERROR(("Client executable \"%s\": is not a regular file", params.binary)); FREE_TEST_PARAMS(params); return 0; }else if( !(stat_buf.st_mode & S_IXUSR) ){ TEST_ERROR(("Client executable \"%s\": has no executable flag", params.binary)); FREE_TEST_PARAMS(params); return 0; } if (PMIX_SUCCESS != (rc = server_init(¶ms))) { FREE_TEST_PARAMS(params); return rc; } cli_init(params.lsize); int launched = 0; /* set namespaces and fork clients */ if (NULL == params.ns_dist) { uint32_t i; int base_rank = 0; /* compute my start counter */ for(i = 0; i < (uint32_t)my_server_id; i++) { base_rank += (params.nprocs % params.nservers) > (uint32_t)i ? params.nprocs / params.nservers + 1 : params.nprocs / params.nservers; } /* we have a single namespace for all clients */ ns_nprocs = params.nprocs; launched += server_launch_clients(params.lsize, params.nprocs, base_rank, ¶ms, &client_env, &client_argv); } else { char *pch; pch = strtok(params.ns_dist, ":"); while (NULL != pch) { ns_nprocs = (int)strtol(pch, NULL, 10); if (params.nprocs < (uint32_t)(launched+ns_nprocs)) { TEST_ERROR(("Total number of processes doesn't correspond number specified by ns_dist parameter.")); FREE_TEST_PARAMS(params); return PMIX_ERROR; } if (0 < ns_nprocs) { launched += server_launch_clients(ns_nprocs, ns_nprocs, 0, ¶ms, &client_env, &client_argv); } pch = strtok (NULL, ":"); } } if (params.lsize != (uint32_t)launched) { TEST_ERROR(("Total number of processes doesn't correspond number specified by ns_dist parameter.")); cli_kill_all(); test_fail = 1; } /* hang around until the client(s) finalize */ while (!test_terminated()) { // To avoid test hang we want to interrupt the loop each 0.1s double test_current; // check if we exceed the max time gettimeofday(&tv, NULL); test_current = tv.tv_sec + 1E-6*tv.tv_usec; if( (test_current - test_start) > params.timeout ){ break; } cli_wait_all(0); } if( !test_terminated() ){ TEST_ERROR(("Test exited by a timeout!")); cli_kill_all(); test_fail = 1; } if( test_abort ){ TEST_ERROR(("Test was aborted!")); /* do not simply kill the clients as that generates * event notifications which these tests then print * out, flooding the log */ // cli_kill_all(); test_fail = 1; } if (0 != params.test_spawn) { PMIX_WAIT_FOR_COMPLETION(spawn_wait); } /* deregister the errhandler */ PMIx_Deregister_event_handler(0, op_callbk, NULL); cli_wait_all(1.0); test_fail += server_finalize(¶ms); FREE_TEST_PARAMS(params); pmix_argv_free(client_argv); pmix_argv_free(client_env); return test_fail; }