static void ttdes(tcp_port_tracker_t *p) { size_t n, m, mstart; if (NULL != p->nspace) { free(p->nspace); } if (NULL != p->src) { if (NULL != p->ports) { mstart = 0; for (n=0; NULL != p->ports[n]; n++) { /* find an empty position */ for (m=mstart; m < p->src->nports; m++) { if (NULL == p->src->ports[m]) { p->src->ports[m] = strdup(p->ports[n]); mstart = m + 1; break; } } } pmix_argv_free(p->ports); } PMIX_RELEASE(p->src); // maintain accounting } else if (NULL != p->ports) { pmix_argv_free(p->ports); } }
/* * Look for and handle any -mca options on the command line */ int pmix_mca_base_cmd_line_process_args(pmix_cmd_line_t *cmd, char ***context_env, char ***global_env) { int i, num_insts, rc; char **params; char **values; /* If no relevant parameters were given, just return */ if (!pmix_cmd_line_is_taken(cmd, PMIX_MCA_CMD_LINE_ID) && !pmix_cmd_line_is_taken(cmd, "g"PMIX_MCA_CMD_LINE_ID)) { return PMIX_SUCCESS; } /* Handle app context-specific parameters */ num_insts = pmix_cmd_line_get_ninsts(cmd, PMIX_MCA_CMD_LINE_ID); params = values = NULL; for (i = 0; i < num_insts; ++i) { if (PMIX_SUCCESS != (rc = process_arg(pmix_cmd_line_get_param(cmd, PMIX_MCA_CMD_LINE_ID, i, 0), pmix_cmd_line_get_param(cmd, PMIX_MCA_CMD_LINE_ID, i, 1), ¶ms, &values))) { return rc; } } if (NULL != params) { add_to_env(params, values, context_env); pmix_argv_free(params); pmix_argv_free(values); } /* Handle global parameters */ num_insts = pmix_cmd_line_get_ninsts(cmd, "g"PMIX_MCA_CMD_LINE_ID); params = values = NULL; for (i = 0; i < num_insts; ++i) { if (PMIX_SUCCESS != (rc = process_arg(pmix_cmd_line_get_param(cmd, "g"PMIX_MCA_CMD_LINE_ID, i, 0), pmix_cmd_line_get_param(cmd, "g"PMIX_MCA_CMD_LINE_ID, i, 1), ¶ms, &values))) { return rc; } } if (NULL != params) { add_to_env(params, values, global_env); pmix_argv_free(params); pmix_argv_free(values); } /* All done */ return PMIX_SUCCESS; }
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 pmix_status_t PMIx_Lookup(pmix_pdata_t pdata[], size_t ndata, const pmix_info_t info[], size_t ninfo) { pmix_status_t rc; pmix_cb_t *cb; char **keys = NULL; size_t i; PMIX_ACQUIRE_THREAD(&pmix_global_lock); pmix_output_verbose(2, pmix_globals.debug_output, "pmix: lookup called"); if (pmix_globals.init_cntr <= 0) { PMIX_RELEASE_THREAD(&pmix_global_lock); return PMIX_ERR_INIT; } /* if we aren't connected, don't attempt to send */ if (!pmix_globals.connected) { PMIX_RELEASE_THREAD(&pmix_global_lock); return PMIX_ERR_UNREACH; } PMIX_RELEASE_THREAD(&pmix_global_lock); /* bozo protection */ if (NULL == pdata) { return PMIX_ERR_BAD_PARAM; } /* transfer the pdata keys to the keys argv array */ for (i=0; i < ndata; i++) { if ('\0' != pdata[i].key[0]) { pmix_argv_append_nosize(&keys, pdata[i].key); } } /* create a callback object as we need to pass it to the * recv routine so we know which callback to use when * the return message is recvd */ cb = PMIX_NEW(pmix_cb_t); cb->cbdata = (void*)pdata; cb->nvals = ndata; if (PMIX_SUCCESS != (rc = PMIx_Lookup_nb(keys, info, ninfo, lookup_cbfunc, cb))) { PMIX_RELEASE(cb); pmix_argv_free(keys); return rc; } /* wait for the server to ack our request */ PMIX_WAIT_THREAD(&cb->lock); /* the data has been stored in the info array by lookup_cbfunc, so * nothing more for us to do */ rc = cb->status; PMIX_RELEASE(cb); return rc; }
static int pdlopen_component_close(void) { if (NULL != mca_pdl_pdlopen_component.filename_suffixes) { pmix_argv_free(mca_pdl_pdlopen_component.filename_suffixes); mca_pdl_pdlopen_component.filename_suffixes = NULL; } return PMIX_SUCCESS; }
int pmix_net_init(void) { char **args, *arg; uint32_t a, b, c, d, bits, addr; int i, count, found_bad = 0; args = pmix_argv_split(pmix_net_private_ipv4, ';'); if( NULL != args ) { count = pmix_argv_count(args); private_ipv4 = (private_ipv4_t*)malloc( (count + 1) * sizeof(private_ipv4_t)); if( NULL == private_ipv4 ) { pmix_output(0, "Unable to allocate memory for the private addresses array" ); pmix_argv_free(args); goto do_local_init; } for( i = 0; i < count; i++ ) { arg = args[i]; (void)sscanf( arg, "%u.%u.%u.%u/%u", &a, &b, &c, &d, &bits ); if( (a > 255) || (b > 255) || (c > 255) || (d > 255) || (bits > 32) ) { if (0 == found_bad) { pmix_show_help("help-pmix-runtime.txt", "malformed net_private_ipv4", true, args[i]); found_bad = 1; } continue; } addr = (a << 24) | (b << 16) | (c << 8) | d; private_ipv4[i].addr = htonl(addr); private_ipv4[i].netmask_bits = bits; } private_ipv4[i].addr = 0; private_ipv4[i].netmask_bits = 0; pmix_argv_free(args); } do_local_init: return pmix_tsd_key_create(&hostname_tsd_key, hostname_cleanup); }
static pmix_status_t pmix_regex_extract_ppn(char *regexp, char ***procs) { char **rngs, **nds, *t, **ps=NULL; int i, j, k, start, end; /* split on semi-colons for nodes */ nds = pmix_argv_split(regexp, ';'); for (j=0; NULL != nds[j]; j++) { /* for each node, split it by comma */ rngs = pmix_argv_split(nds[j], ','); /* parse each element */ for (i=0; NULL != rngs[i]; i++) { /* look for a range */ if (NULL == (t = strchr(rngs[i], '-'))) { /* just one value */ pmix_argv_append_nosize(&ps, rngs[i]); } else { /* handle the range */ *t = '\0'; start = strtol(rngs[i], NULL, 10); ++t; end = strtol(t, NULL, 10); for (k=start; k <= end; k++) { asprintf(&t, "%d", k); pmix_argv_append_nosize(&ps, t); free(t); } } } pmix_argv_free(rngs); /* create the node entry */ t = pmix_argv_join(ps, ','); pmix_argv_append_nosize(procs, t); free(t); pmix_argv_free(ps); ps = NULL; } pmix_argv_free(nds); return PMIX_SUCCESS; }
static void tades(tcp_available_ports_t *p) { PMIX_LIST_DESTRUCT(&p->devices); if (NULL != p->type) { free(p->type); } if (NULL != p->plane) { free(p->plane); } if (NULL != p->ports) { pmix_argv_free(p->ports); } }
int PMIx_Lookup(pmix_data_range_t scope, const pmix_info_t info[], size_t ninfo, pmix_pdata_t pdata[], size_t ndata) { int rc; pmix_cb_t *cb; char **keys = NULL; size_t i; pmix_output_verbose(2, pmix_globals.debug_output, "pmix: lookup called"); /* bozo protection */ if (NULL == pdata) { return PMIX_ERR_BAD_PARAM; } /* transfer the pdata keys to the keys argv array */ for (i=0; i < ndata; i++) { if ('\0' != pdata[i].key[0]) { pmix_argv_append_nosize(&keys, pdata[i].key); } } /* create a callback object as we need to pass it to the * recv routine so we know which callback to use when * the return message is recvd */ cb = PMIX_NEW(pmix_cb_t); cb->cbdata = (void*)pdata; cb->nvals = ndata; cb->active = true; if (PMIX_SUCCESS != (rc = PMIx_Lookup_nb(scope, keys, info, ninfo, lookup_cbfunc, cb))) { PMIX_RELEASE(cb); pmix_argv_free(keys); return rc; } /* wait for the server to ack our request */ PMIX_WAIT_FOR_COMPLETION(cb->active); /* the data has been stored in the info array by lookup_cbfunc, so * nothing more for us to do */ rc = cb->status; PMIX_RELEASE(cb); return rc; }
/* * Locates a file with certain permissions from a list of search paths */ char *pmix_path_findv(char *fname, int mode, char **envv, char *wrkdir) { char **dirv; char *fullpath; char *path; int dirc; int i; bool found_dot = false; /* Set the local search paths. */ dirc = 0; dirv = NULL; if (NULL != (path = list_env_get("PATH", envv))) { path_env_load(path, &dirc, &dirv); } /* Replace the "." path by the working directory. */ if (NULL != wrkdir) { for (i = 0; i < dirc; ++i) { if (0 == strcmp(dirv[i], ".")) { found_dot = true; free(dirv[i]); dirv[i] = strdup(wrkdir); if (NULL == dirv[i]){ return NULL; } } } } /* If we didn't find "." in the path and we have a wrkdir, append the wrkdir to the end of the path */ if (!found_dot && NULL != wrkdir) { pmix_argv_append(&dirc, &dirv, wrkdir); } if(NULL == dirv) return NULL; fullpath = pmix_path_find(fname, dirv, mode, envv); pmix_argv_free(dirv); return fullpath; }
static void finalize(void) { pmix_argv_free(pmix_plog_stdfd_module.channels); }
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; }
static pmix_status_t validate_cred(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, const pmix_byte_object_t *cred) { pmix_peer_t *pr = (pmix_peer_t*)peer; #if defined(SO_PEERCRED) #ifdef HAVE_STRUCT_SOCKPEERCRED_UID #define HAVE_STRUCT_UCRED_UID struct sockpeercred ucred; #else struct ucred ucred; #endif socklen_t crlen = sizeof (ucred); #endif uid_t euid = -1; gid_t egid = -1; char *ptr; size_t ln; bool takeus; char **types; size_t n, m; uint32_t u32; pmix_output_verbose(2, pmix_globals.debug_output, "psec: native validate_cred %s", (NULL == cred) ? "NULL" : "NON-NULL"); if (PMIX_PROTOCOL_V1 == pr->protocol) { /* usock protocol - get the remote side's uid/gid */ #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID)) /* Ignore received 'cred' and validate ucred for socket instead. */ pmix_output_verbose(2, pmix_globals.debug_output, "psec:native checking getsockopt on socket %d for peer credentials", pr->sd); if (getsockopt(pr->sd, SOL_SOCKET, SO_PEERCRED, &ucred, &crlen) < 0) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: getsockopt SO_PEERCRED failed: %s", strerror (pmix_socket_errno)); return PMIX_ERR_INVALID_CRED; } #if defined(HAVE_STRUCT_UCRED_UID) euid = ucred.uid; egid = ucred.gid; #else euid = ucred.cr_uid; egid = ucred.cr_gid; #endif #elif defined(HAVE_GETPEEREID) pmix_output_verbose(2, pmix_globals.debug_output, "psec:native checking getpeereid on socket %d for peer credentials", pr->sd); if (0 != getpeereid(pr->sd, &euid, &egid)) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: getsockopt getpeereid failed: %s", strerror (pmix_socket_errno)); return PMIX_ERR_INVALID_CRED; } #else return PMIX_ERR_NOT_SUPPORTED; #endif } else if (PMIX_PROTOCOL_V2 == pr->protocol) { /* this is a tcp protocol, so the cred is actually the uid/gid * passed upwards from the client */ if (NULL == cred) { /* not allowed */ return PMIX_ERR_INVALID_CRED; } ln = cred->size; euid = 0; egid = 0; if (sizeof(uid_t) <= ln) { memcpy(&euid, cred->bytes, sizeof(uid_t)); ln -= sizeof(uid_t); ptr = cred->bytes + sizeof(uid_t); } else { return PMIX_ERR_INVALID_CRED; } if (sizeof(gid_t) <= ln) { memcpy(&egid, ptr, sizeof(gid_t)); } else { return PMIX_ERR_INVALID_CRED; } } else if (PMIX_PROTOCOL_UNDEF != pr->protocol) { /* don't recognize the protocol */ return PMIX_ERR_NOT_SUPPORTED; } /* if we are responding to a local request to validate a credential, * then see if they specified a mechanism */ if (NULL != directives && 0 < ndirs) { for (n=0; n < ndirs; n++) { if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) { /* split the specified string */ types = pmix_argv_split(directives[n].value.data.string, ','); takeus = false; for (m=0; NULL != types[m]; m++) { if (0 == strcmp(types[m], "native")) { /* it's us! */ takeus = true; break; } } pmix_argv_free(types); if (!takeus) { return PMIX_ERR_NOT_SUPPORTED; } } } } /* check uid */ if (euid != pr->info->uid) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: socket cred contains invalid uid %u", euid); return PMIX_ERR_INVALID_CRED; } /* check gid */ if (egid != pr->info->gid) { pmix_output_verbose(2, pmix_globals.debug_output, "psec: socket cred contains invalid gid %u", egid); return PMIX_ERR_INVALID_CRED; } /* validated - mark that we did it */ if (NULL != info) { PMIX_INFO_CREATE(*info, 3); if (NULL == *info) { return PMIX_ERR_NOMEM; } *ninfo = 3; /* mark that this came from us */ PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "munge", PMIX_STRING); /* provide the uid it contained */ u32 = euid; PMIX_INFO_LOAD(info[1], PMIX_USERID, &u32, PMIX_UINT32); /* provide the gid it contained */ u32 = egid; PMIX_INFO_LOAD(info[2], PMIX_GRPID, &u32, PMIX_UINT32); } return PMIX_SUCCESS; }
static pmix_status_t create_cred(struct pmix_peer_t *peer, const pmix_info_t directives[], size_t ndirs, pmix_info_t **info, size_t *ninfo, pmix_byte_object_t *cred) { pmix_peer_t *pr = (pmix_peer_t*)peer; char **types; size_t n, m; bool takeus; uid_t euid; gid_t egid; char *tmp, *ptr; /* ensure initialization */ PMIX_BYTE_OBJECT_CONSTRUCT(cred); /* we may be responding to a local request for a credential, so * see if they specified a mechanism */ if (NULL != directives && 0 < ndirs) { /* cycle across the provided info and see if they specified * any desired credential types */ takeus = true; for (n=0; n < ndirs; n++) { if (0 == strncmp(directives[n].key, PMIX_CRED_TYPE, PMIX_MAX_KEYLEN)) { /* see if we are included */ types = pmix_argv_split(directives[n].value.data.string, ','); /* start by assuming they don't want us */ takeus = false; for (m=0; NULL != types[m]; m++) { if (0 == strcmp(types[m], "native")) { /* it's us! */ takeus = true; break; } } pmix_argv_free(types); break; } } if (!takeus) { PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED); return PMIX_ERR_NOT_SUPPORTED; } } if (PMIX_PROTOCOL_V1 == pr->protocol) { /* usock protocol - nothing to do */ goto complete; } else if (PMIX_PROTOCOL_V2 == pr->protocol) { /* tcp protocol - need to provide our effective * uid and gid for validation on remote end */ tmp = (char*)malloc(sizeof(uid_t) + sizeof(gid_t)); if (NULL == tmp) { return PMIX_ERR_NOMEM; } euid = geteuid(); memcpy(tmp, &euid, sizeof(uid_t)); ptr = tmp + sizeof(uid_t); egid = getegid(); memcpy(ptr, &egid, sizeof(gid_t)); cred->bytes = tmp; cred->size = sizeof(uid_t) + sizeof(gid_t); goto complete; } else { /* unrecognized protocol */ PMIX_ERROR_LOG(PMIX_ERR_NOT_SUPPORTED); return PMIX_ERR_NOT_SUPPORTED; } complete: if (NULL != info) { /* mark that this came from us */ PMIX_INFO_CREATE(*info, 1); if (NULL == *info) { return PMIX_ERR_NOMEM; } *ninfo = 1; PMIX_INFO_LOAD(info[0], PMIX_CRED_TYPE, "native", PMIX_STRING); } return PMIX_SUCCESS; }
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; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { struct sockaddr_un *address; char *evar, **uri; pmix_status_t rc; int sd; pmix_socklen_t len; bool retried = false; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "[%s:%d] connect to server", __FILE__, __LINE__); /* if we are not a client, there is nothing we can do */ if (!PMIX_PROC_IS_CLIENT(pmix_globals.mypeer)) { return PMIX_ERR_NOT_SUPPORTED; } /* if we don't have a path to the daemon rendezvous point, * then we need to return an error */ if (NULL != (evar = getenv("PMIX_SERVER_URI2USOCK"))) { /* this is a v2.1+ server */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v21"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else if (NULL != (evar = getenv("PMIX_SERVER_URI"))) { /* this is a pre-v2.1 server - must use the v12 bfrops module */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v12"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else { /* let the caller know that the server isn't available */ return PMIX_ERR_SERVER_NOT_AVAIL; } /* the server will be using the same bfrops as us */ pmix_client_globals.myserver->nptr->compat.bfrops = pmix_globals.mypeer->nptr->compat.bfrops; /* mark that we are using the V1 protocol */ pmix_globals.mypeer->protocol = PMIX_PROTOCOL_V1; uri = pmix_argv_split(evar, ':'); if (3 != pmix_argv_count(uri)) { pmix_argv_free(uri); PMIX_ERROR_LOG(PMIX_ERROR); return PMIX_ERROR; } /* set the server nspace */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_namespace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = strdup(uri[0]); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(uri[0]); } /* set the server rank */ pmix_client_globals.myserver->info->pname.rank = strtoull(uri[1], NULL, 10); /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_usock_component.connection, 0, sizeof(struct sockaddr_storage)); address = (struct sockaddr_un*)&mca_ptl_usock_component.connection; address->sun_family = AF_UNIX; snprintf(address->sun_path, sizeof(address->sun_path)-1, "%s", uri[2]); /* if the rendezvous file doesn't exist, that's an error */ if (0 != access(uri[2], R_OK)) { pmix_argv_free(uri); PMIX_ERROR_LOG(PMIX_ERR_NOT_FOUND); return PMIX_ERR_NOT_FOUND; } pmix_argv_free(uri); retry: /* establish the connection */ len = sizeof(struct sockaddr_un); if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_usock_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver->sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); if (PMIX_ERR_TEMP_UNAVAILABLE == rc) { /* give it two tries */ if (!retried) { retried = true; goto retry; } } return rc; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_usock_recv_handler, pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); pmix_client_globals.myserver->recv_ev_active = true; PMIX_POST_OBJECT(pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_usock_send_handler, pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { char *evar, **uri, *suri; char *filename, *nspace=NULL; pmix_rank_t rank = PMIX_RANK_WILDCARD; char *p, *p2; int sd, rc; size_t n; char myhost[PMIX_MAXHOSTNAMELEN]; bool system_level = false; bool system_level_only = false; pid_t pid = 0; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp: connecting to server"); /* see if the connection info is in the info array - if * so, then that overrides all other options */ /* if I am a client, then we need to look for the appropriate * connection info in the environment */ if (PMIX_PROC_IS_CLIENT(pmix_globals.mypeer)) { if (NULL != (evar = getenv("PMIX_SERVER_URI21"))) { /* we are talking to a v2.1 server */ pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V21; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "V21 SERVER DETECTED"); /* must use the v21 bfrops module */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v21"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else if (NULL != (evar = getenv("PMIX_SERVER_URI2"))) { /* we are talking to a v2.0 server */ pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V20; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "V20 SERVER DETECTED"); /* must use the v20 bfrops module */ pmix_globals.mypeer->nptr->compat.bfrops = pmix_bfrops_base_assign_module("v20"); if (NULL == pmix_globals.mypeer->nptr->compat.bfrops) { return PMIX_ERR_INIT; } } else { /* not us */ return PMIX_ERR_NOT_SUPPORTED; } /* the server will be using the same bfrops as us */ pmix_client_globals.myserver->nptr->compat.bfrops = pmix_globals.mypeer->nptr->compat.bfrops; /* mark that we are using the V2 protocol */ pmix_globals.mypeer->protocol = PMIX_PROTOCOL_V2; /* the URI consists of the following elements: * - server nspace.rank * - ptl rendezvous URI */ uri = pmix_argv_split(evar, ';'); if (2 != pmix_argv_count(uri)) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } /* set the server nspace */ p = uri[0]; if (NULL == (p2 = strchr(p, '.'))) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } *p2 = '\0'; ++p2; nspace = strdup(p); rank = strtoull(p2, NULL, 10); /* save the URI, but do not overwrite what we may have received from * the info-key directives */ if (NULL == mca_ptl_tcp_component.super.uri) { mca_ptl_tcp_component.super.uri = strdup(uri[1]); } pmix_argv_free(uri); pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:client attempt connect to %s", mca_ptl_tcp_component.super.uri); /* go ahead and try to connect */ if (PMIX_SUCCESS != (rc = try_connect(&sd))) { free(nspace); return rc; } goto complete; } /* get here if we are a tool - check any provided directives * to see where they want us to connect to */ if (NULL != info) { for (n=0; n < ninfo; n++) { if (0 == strcmp(info[n].key, PMIX_CONNECT_TO_SYSTEM)) { system_level_only = PMIX_INFO_TRUE(&info[n]); } else if (0 == strcmp(info[n].key, PMIX_CONNECT_SYSTEM_FIRST)) { /* try the system-level */ system_level = PMIX_INFO_TRUE(&info[n]); } else if (0 == strcmp(info[n].key, PMIX_SERVER_PIDINFO)) { pid = info[n].value.data.pid; } else if (0 == strcmp(info[n].key, PMIX_SERVER_URI)) { if (NULL == mca_ptl_tcp_component.super.uri) { free(mca_ptl_tcp_component.super.uri); } mca_ptl_tcp_component.super.uri = strdup(info[n].value.data.string); } else if (0 == strcmp(info[n].key, PMIX_CONNECT_RETRY_DELAY)) { mca_ptl_tcp_component.wait_to_connect = info[n].value.data.uint32; } else if (0 == strcmp(info[n].key, PMIX_CONNECT_MAX_RETRIES)) { mca_ptl_tcp_component.max_retries = info[n].value.data.uint32; } } } /* mark that we are using the V2 protocol */ pmix_globals.mypeer->protocol = PMIX_PROTOCOL_V2; gethostname(myhost, sizeof(myhost)); /* if we were given a URI via MCA param, then look no further */ if (NULL != mca_ptl_tcp_component.super.uri) { /* if the string starts with "file:", then they are pointing * us to a file we need to read to get the URI itself */ if (0 == strncmp(mca_ptl_tcp_component.super.uri, "file:", 5)) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool getting connection info from %s", mca_ptl_tcp_component.super.uri); nspace = NULL; rc = parse_uri_file(&mca_ptl_tcp_component.super.uri[5], &suri, &nspace, &rank); if (PMIX_SUCCESS != rc) { return PMIX_ERR_UNREACH; } free(mca_ptl_tcp_component.super.uri); mca_ptl_tcp_component.super.uri = suri; } else { /* we need to extract the nspace/rank of the server from the string */ p = strchr(mca_ptl_tcp_component.super.uri, ';'); if (NULL == p) { return PMIX_ERR_BAD_PARAM; } *p = '\0'; p++; suri = strdup(p); // save the uri portion /* the '.' in the first part of the original string separates * nspace from rank */ p = strchr(mca_ptl_tcp_component.super.uri, '.'); if (NULL == p) { free(suri); return PMIX_ERR_BAD_PARAM; } *p = '\0'; p++; nspace = strdup(mca_ptl_tcp_component.super.uri); rank = strtoull(p, NULL, 10); /* now update the URI */ free(mca_ptl_tcp_component.super.uri); mca_ptl_tcp_component.super.uri = suri; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool attempt connect using given URI %s", mca_ptl_tcp_component.super.uri); /* go ahead and try to connect */ if (PMIX_SUCCESS != (rc = try_connect(&sd))) { if (NULL != nspace) { free(nspace); } return rc; } goto complete; } /* if they gave us a pid, then look for it */ if (0 != pid) { if (0 > asprintf(&filename, "pmix.%s.tool.%d", myhost, pid)) { return PMIX_ERR_NOMEM; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool searching for given session server %s", filename); nspace = NULL; rc = df_search(mca_ptl_tcp_component.system_tmpdir, filename, &sd, &nspace, &rank); free(filename); if (PMIX_SUCCESS == rc) { goto complete; } if (NULL != nspace) { free(nspace); } /* since they gave us a specific pid and we couldn't * connect to it, return an error */ return PMIX_ERR_UNREACH; } /* if they asked for system-level, we start there */ if (system_level || system_level_only) { if (0 > asprintf(&filename, "%s/pmix.sys.%s", mca_ptl_tcp_component.system_tmpdir, myhost)) { return PMIX_ERR_NOMEM; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool looking for system server at %s", filename); /* try to read the file */ rc = parse_uri_file(filename, &suri, &nspace, &rank); free(filename); if (PMIX_SUCCESS == rc) { mca_ptl_tcp_component.super.uri = suri; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool attempt connect to system server at %s", mca_ptl_tcp_component.super.uri); /* go ahead and try to connect */ if (PMIX_SUCCESS == try_connect(&sd)) { goto complete; } free(nspace); } } /* we get here if they either didn't ask for a system-level connection, * or they asked for it and it didn't succeed. If they _only_ wanted * a system-level connection, then we are done */ if (system_level_only) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp: connecting to system failed"); return PMIX_ERR_UNREACH; } /* they didn't give us a pid, so we will search to see what session-level * tools are available to this user. We will take the first connection * that succeeds - this is based on the likelihood that there is only * one session per user on a node */ if (0 > asprintf(&filename, "pmix.%s.tool", myhost)) { return PMIX_ERR_NOMEM; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "ptl:tcp:tool searching for session server %s", filename); nspace = NULL; rc = df_search(mca_ptl_tcp_component.system_tmpdir, filename, &sd, &nspace, &rank); free(filename); if (PMIX_SUCCESS != rc) { if (NULL != nspace){ free(nspace); } return PMIX_ERR_UNREACH; } complete: pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "sock_peer_try_connect: Connection across to server succeeded"); /* do a final bozo check */ if (NULL == nspace || PMIX_RANK_WILDCARD == rank) { if (NULL != nspace) { free(nspace); } CLOSE_THE_SOCKET(sd); return PMIX_ERR_UNREACH; } /* mark the connection as made */ pmix_globals.connected = true; pmix_client_globals.myserver->sd = sd; /* setup the server info */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = nspace; } else { free(nspace); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(pmix_client_globals.myserver->nptr->nspace); } pmix_client_globals.myserver->info->pname.rank = rank; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, pmix_client_globals.myserver); pmix_client_globals.myserver->recv_ev_active = true; PMIX_POST_OBJECT(pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { struct sockaddr_un *address; char *evar, **uri; pmix_status_t rc; int sd; pmix_socklen_t len; /* if we are not a client, there is nothing we can do */ if (!PMIX_PROC_IS_CLIENT) { return PMIX_ERR_NOT_SUPPORTED; } /* if we don't have a path to the daemon rendezvous point, * then we need to return an error */ if (NULL == (evar = getenv("PMIX_SERVER_URI"))) { /* let the caller know that the server isn't available */ return PMIX_ERR_SERVER_NOT_AVAIL; } uri = pmix_argv_split(evar, ':'); if (3 != pmix_argv_count(uri)) { pmix_argv_free(uri); return PMIX_ERROR; } /* set the server nspace */ if (NULL == pmix_client_globals.myserver->info) { pmix_client_globals.myserver->info = PMIX_NEW(pmix_rank_info_t); } if (NULL == pmix_client_globals.myserver->nptr) { pmix_client_globals.myserver->nptr = PMIX_NEW(pmix_nspace_t); } if (NULL == pmix_client_globals.myserver->nptr->nspace) { pmix_client_globals.myserver->nptr->nspace = strdup(uri[0]); } if (NULL == pmix_client_globals.myserver->info->pname.nspace) { pmix_client_globals.myserver->info->pname.nspace = strdup(uri[0]); } /* set the server rank */ pmix_client_globals.myserver->info->pname.rank = strtoull(uri[1], NULL, 10); /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_usock_component.connection, 0, sizeof(struct sockaddr_storage)); address = (struct sockaddr_un*)&mca_ptl_usock_component.connection; address->sun_family = AF_UNIX; snprintf(address->sun_path, sizeof(address->sun_path)-1, "%s", uri[2]); /* if the rendezvous file doesn't exist, that's an error */ if (0 != access(uri[2], R_OK)) { pmix_argv_free(uri); return PMIX_ERR_NOT_FOUND; } pmix_argv_free(uri); /* establish the connection */ len = sizeof(struct sockaddr_un); if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_usock_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver->sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { CLOSE_THE_SOCKET(sd); return rc; } pmix_output_verbose(2, pmix_globals.debug_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver->recv_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, &pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver->recv_event, 0); pmix_client_globals.myserver->recv_ev_active = true; /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver->send_event, pmix_globals.evbase, pmix_client_globals.myserver->sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, &pmix_client_globals.myserver); pmix_client_globals.myserver->send_ev_active = false; return PMIX_SUCCESS; }
/* * Function to find as many components of a given type as possible. This * includes statically-linked in components as well as opening up a * directory and looking for shared-library MCA components of the * appropriate type (load them if available). * * Return one consolidated array of (pmix_mca_base_component_t*) pointing to all * available components. */ int pmix_mca_base_component_find (const char *directory, pmix_mca_base_framework_t *framework, bool ignore_requested, bool open_dso_components) { const pmix_mca_base_component_t **static_components = framework->framework_static_components; char **requested_component_names = NULL; pmix_mca_base_component_list_item_t *cli; bool include_mode = true; int ret; pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_COMPONENT, framework->framework_output, "mca: base: component_find: searching %s for %s components", directory, framework->framework_name); if (!ignore_requested) { ret = pmix_mca_base_component_parse_requested (framework->framework_selection, &include_mode, &requested_component_names); if (PMIX_SUCCESS != ret) { return ret; } } /* Find all the components that were statically linked in */ if (static_components) { for (int i = 0 ; NULL != static_components[i]; ++i) { if ( use_component(include_mode, (const char**)requested_component_names, static_components[i]->pmix_mca_component_name) ) { cli = PMIX_NEW(pmix_mca_base_component_list_item_t); if (NULL == cli) { ret = PMIX_ERR_OUT_OF_RESOURCE; goto component_find_out; } cli->cli_component = static_components[i]; pmix_list_append(&framework->framework_components, (pmix_list_item_t *) cli); } } } #if PMIX_HAVE_PDL_SUPPORT /* Find any available dynamic components in the specified directory */ if (open_dso_components && !pmix_mca_base_component_disable_dlopen) { find_dyn_components(directory, framework, (const char**)requested_component_names, include_mode); } else { pmix_output_verbose (PMIX_MCA_BASE_VERBOSE_INFO, 0, "pmix:mca: base: component_find: dso loading for %s MCA components disabled", framework->framework_name); } #endif if (include_mode) { ret = component_find_check (framework, requested_component_names); } else { ret = PMIX_SUCCESS; } component_find_out: if (NULL != requested_component_names) { pmix_argv_free(requested_component_names); } /* All done */ return ret; }
int pmix_mca_base_components_filter (pmix_mca_base_framework_t *framework, uint32_t filter_flags) { pmix_list_t *components = &framework->framework_components; int output_id = framework->framework_output; pmix_mca_base_component_list_item_t *cli, *next; char **requested_component_names = NULL; bool include_mode, can_use; int ret; assert (NULL != components); if (0 == filter_flags && NULL == framework->framework_selection) { return PMIX_SUCCESS; } ret = pmix_mca_base_component_parse_requested (framework->framework_selection, &include_mode, &requested_component_names); if (PMIX_SUCCESS != ret) { return ret; } PMIX_LIST_FOREACH_SAFE(cli, next, components, pmix_mca_base_component_list_item_t) { const pmix_mca_base_component_t *component = cli->cli_component; pmix_mca_base_open_only_dummy_component_t *dummy = (pmix_mca_base_open_only_dummy_component_t *) cli->cli_component; can_use = use_component(include_mode, (const char **) requested_component_names, cli->cli_component->pmix_mca_component_name); if (!can_use || (filter_flags & dummy->data.param_field) != filter_flags) { if (can_use && (filter_flags & PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT) && !(PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT & dummy->data.param_field)) { pmix_output_verbose(PMIX_MCA_BASE_VERBOSE_COMPONENT, output_id, "pmix:mca: base: components_filter: " "(%s) Component %s is *NOT* Checkpointable - Disabled", component->reserved, component->pmix_mca_component_name); } pmix_list_remove_item(components, &cli->super); pmix_mca_base_component_unload(component, output_id); PMIX_RELEASE(cli); } else if (filter_flags & PMIX_MCA_BASE_METADATA_PARAM_CHECKPOINT) { pmix_output_verbose(PMIX_MCA_BASE_VERBOSE_COMPONENT, output_id, "pmix:mca: base: components_filter: " "(%s) Component %s is Checkpointable", component->reserved, component->pmix_mca_component_name); } } if (include_mode) { ret = component_find_check(framework, requested_component_names); } else { ret = PMIX_SUCCESS; } if (NULL != requested_component_names) { pmix_argv_free(requested_component_names); } return ret; }
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; }
static pmix_status_t tcp_init(void) { tcp_available_ports_t *trk; char *p, **grps; size_t n; pmix_output_verbose(2, pmix_pnet_base_framework.framework_output, "pnet: tcp init"); /* if we are not the "gateway", then there is nothing * for us to do */ if (!PMIX_PROC_IS_GATEWAY(pmix_globals.mypeer)) { return PMIX_SUCCESS; } PMIX_CONSTRUCT(&allocations, pmix_list_t); PMIX_CONSTRUCT(&available, pmix_list_t); /* if we have no static ports, then we don't have * anything to manage. However, we cannot just disqualify * ourselves as we may still need to provide inventory. * * NOTE: need to check inventory in addition to MCA param as * the inventory may have reported back static ports */ if (NULL == mca_pnet_tcp_component.static_ports) { return PMIX_SUCCESS; } /* split on semi-colons */ grps = pmix_argv_split(mca_pnet_tcp_component.static_ports, ';'); for (n=0; NULL != grps[n]; n++) { trk = PMIX_NEW(tcp_available_ports_t); if (NULL == trk) { pmix_argv_free(grps); return PMIX_ERR_NOMEM; } /* there must be at least one colon */ if (NULL == (p = strrchr(grps[n], ':'))) { pmix_argv_free(grps); return PMIX_ERR_BAD_PARAM; } /* extract the ports */ *p = '\0'; ++p; pmix_util_parse_range_options(p, &trk->ports); trk->nports = pmix_argv_count(trk->ports); /* see if they provided a plane */ if (NULL != (p = strchr(grps[n], ':'))) { /* yep - save the plane */ *p = '\0'; ++p; trk->plane = strdup(p); } /* the type is just what is left at the front */ trk->type = strdup(grps[n]); pmix_output_verbose(2, pmix_pnet_base_framework.framework_output, "TYPE: %s PLANE %s", trk->type, (NULL == trk->plane) ? "NULL" : trk->plane); pmix_list_append(&available, &trk->super); } pmix_argv_free(grps); return PMIX_SUCCESS; }
static pmix_status_t connect_to_peer(struct pmix_peer_t *peer, pmix_info_t *info, size_t ninfo) { char *evar, **uri; char *filename, *host; FILE *fp; char *srvr, *p, *p2; struct sockaddr_in *in; struct sockaddr_in6 *in6; pmix_socklen_t len; int sd, rc; pmix_output_verbose(2, pmix_globals.debug_output, "ptl:tcp: connecting to server"); /* see if the connection info is in the info array - if * so, then that overrides all other options */ /* if I am a client, then we need to look for the appropriate * connection info in the environment */ if (PMIX_PROC_CLIENT == pmix_globals.proc_type) { if (NULL == (evar = getenv("PMIX_SERVER_URI2"))) { /* not us */ return PMIX_ERR_NOT_SUPPORTED; } /* the URI consists of elements: * - server nspace.rank * - ptl rendezvous URI */ uri = pmix_argv_split(evar, ';'); if (2 != pmix_argv_count(uri)) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } /* set the server nspace */ p = uri[0]; if (NULL == (p2 = strchr(p, '.'))) { PMIX_ERROR_LOG(PMIX_ERR_BAD_PARAM); pmix_argv_free(uri); return PMIX_ERR_NOT_SUPPORTED; } *p2 = '\0'; ++p2; pmix_client_globals.myserver.info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver.info->nptr = PMIX_NEW(pmix_nspace_t); (void)strncpy(pmix_client_globals.myserver.info->nptr->nspace, p, PMIX_MAX_NSLEN); /* set the server rank */ pmix_client_globals.myserver.info->rank = strtoull(p2, NULL, 10); /* save the URI, but do not overwrite what we may have received from * the info-key directives */ if (NULL == mca_ptl_tcp_component.super.uri) { mca_ptl_tcp_component.super.uri = strdup(uri[1]); } pmix_argv_free(uri); } else if (PMIX_PROC_TOOL == pmix_globals.proc_type) { /* if we already have a URI, then look no further */ if (NULL == mca_ptl_tcp_component.super.uri) { /* we have to discover the connection info, * if possible. Start by looking for the connection * info in the expected place - if the server supports * tool connections via TCP, then there will be a * "contact.txt" file under the system tmpdir */ filename = pmix_os_path(false, mca_ptl_tcp_component.tmpdir, "pmix-contact.txt", NULL); if (NULL == filename) { return PMIX_ERR_NOMEM; } fp = fopen(filename, "r"); if (NULL == fp) { /* if we cannot open the file, then the server must not * be configured to support tool connections - so abort */ free(filename); return PMIX_ERR_UNREACH; } free(filename); /* get the URI */ srvr = pmix_getline(fp); if (NULL == srvr) { PMIX_ERROR_LOG(PMIX_ERR_FILE_READ_FAILURE); fclose(fp); return PMIX_ERR_UNREACH; } fclose(fp); /* up to the first ';' is the server nspace/rank */ if (NULL == (p = strchr(srvr, ';'))) { /* malformed */ free(srvr); return PMIX_ERR_UNREACH; } *p = '\0'; ++p; // move past the semicolon /* the nspace is the section up to the '.' */ if (NULL == (p2 = strchr(srvr, '.'))) { /* malformed */ free(srvr); return PMIX_ERR_UNREACH; } *p2 = '\0'; ++p2; /* set the server nspace */ pmix_client_globals.myserver.info = PMIX_NEW(pmix_rank_info_t); pmix_client_globals.myserver.info->nptr = PMIX_NEW(pmix_nspace_t); (void)strncpy(pmix_client_globals.myserver.info->nptr->nspace, srvr, PMIX_MAX_NSLEN); pmix_client_globals.myserver.info->rank = strtoull(p2, NULL, 10); /* now parse the uti itself */ mca_ptl_tcp_component.super.uri = strdup(p); free(srvr); } } /* mark that we are the active module for this server */ pmix_client_globals.myserver.compat.ptl = &pmix_ptl_tcp_module; /* setup the path to the daemon rendezvous point */ memset(&mca_ptl_tcp_component.connection, 0, sizeof(struct sockaddr_storage)); if (0 == strncmp(mca_ptl_tcp_component.super.uri, "tcp4", 4)) { /* separate the IP address from the port */ p = strdup(mca_ptl_tcp_component.super.uri); if (NULL == p) { return PMIX_ERR_NOMEM; } p2 = strchr(&p[7], ':'); if (NULL == p2) { free(p); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; ++p2; host = &p[7]; /* load the address */ in = (struct sockaddr_in*)&mca_ptl_tcp_component.connection; in->sin_family = AF_INET; in->sin_addr.s_addr = inet_addr(host); if (in->sin_addr.s_addr == INADDR_NONE) { free(p); return PMIX_ERR_BAD_PARAM; } in->sin_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in); } else { /* separate the IP address from the port */ p = strdup(mca_ptl_tcp_component.super.uri); if (NULL == p) { return PMIX_ERR_NOMEM; } p2 = strchr(&p[7], ':'); if (NULL == p2) { free(p); return PMIX_ERR_BAD_PARAM; } *p2 = '\0'; if (']' == p[strlen(p)-1]) { p[strlen(p)-1] = '\0'; } if ('[' == p[7]) { host = &p[8]; } else { host = &p[7]; } /* load the address */ in6 = (struct sockaddr_in6*)&mca_ptl_tcp_component.connection; in6->sin6_family = AF_INET6; if (0 == inet_pton(AF_INET6, host, (void*)&in6->sin6_addr)) { pmix_output (0, "ptl_tcp_parse_uri: Could not convert %s\n", host); free(p); return PMIX_ERR_BAD_PARAM; } in6->sin6_port = htons(atoi(p2)); len = sizeof(struct sockaddr_in6); } free(p); /* establish the connection */ if (PMIX_SUCCESS != (rc = pmix_ptl_base_connect(&mca_ptl_tcp_component.connection, len, &sd))) { PMIX_ERROR_LOG(rc); return rc; } pmix_client_globals.myserver.sd = sd; /* send our identity and any authentication credentials to the server */ if (PMIX_SUCCESS != (rc = send_connect_ack(sd))) { PMIX_ERROR_LOG(rc); CLOSE_THE_SOCKET(sd); return rc; } /* do whatever handshake is required */ if (PMIX_SUCCESS != (rc = recv_connect_ack(sd))) { PMIX_ERROR_LOG(rc); CLOSE_THE_SOCKET(sd); return rc; } pmix_output_verbose(2, pmix_globals.debug_output, "sock_peer_try_connect: Connection across to server succeeded"); /* mark the connection as made */ pmix_globals.connected = true; pmix_ptl_base_set_nonblocking(sd); /* setup recv event */ pmix_event_assign(&pmix_client_globals.myserver.recv_event, pmix_globals.evbase, pmix_client_globals.myserver.sd, EV_READ | EV_PERSIST, pmix_ptl_base_recv_handler, &pmix_client_globals.myserver); pmix_event_add(&pmix_client_globals.myserver.recv_event, 0); pmix_client_globals.myserver.recv_ev_active = true; /* setup send event */ pmix_event_assign(&pmix_client_globals.myserver.send_event, pmix_globals.evbase, pmix_client_globals.myserver.sd, EV_WRITE|EV_PERSIST, pmix_ptl_base_send_handler, &pmix_client_globals.myserver); pmix_client_globals.myserver.send_ev_active = false; return PMIX_SUCCESS; }
void parse_cmd(int argc, char **argv, test_params *params) { int i; /* set output to stderr by default */ file = stdout; if( params->nspace != NULL ) { params->nspace = NULL; } /* parse user options */ for (i=1; i < argc; i++) { if (0 == strcmp(argv[i], "--n") || 0 == strcmp(argv[i], "-n")) { i++; if (NULL != argv[i]) { params->np = strdup(argv[i]); params->nprocs = strtol(argv[i], NULL, 10); if (-1 == params->ns_size) { params->ns_size = params->nprocs; } } } else if (0 == strcmp(argv[i], "--h") || 0 == strcmp(argv[i], "-h")) { /* print help */ fprintf(stderr, "usage: pmix_test [-h] [-e foo] [-b] [-c] [-nb]\n"); fprintf(stderr, "\t-n provides information about the job size (for checking purposes)\n"); fprintf(stderr, "\t-e foo use foo as test client\n"); fprintf(stderr, "\t-v verbose output\n"); fprintf(stderr, "\t-t <> set timeout\n"); fprintf(stderr, "\t-o out redirect clients logs to file out.<rank>\n"); fprintf(stderr, "\t--early-fail force client process with rank 0 to fail before PMIX_Init.\n"); fprintf(stderr, "\t--ns-dist n1:n2:n3 register n namespaces (3 in this example) each with ni ranks (n1, n2 or n3).\n"); fprintf(stderr, "\t--fence \"[<data_exchange><blocking> | ns0:ranks;ns1:ranks...][...]\" specify fences in different configurations.\n"); fprintf(stderr, "\t--use-same-keys relative to the --fence option: put the same keys in the interim between multiple fences.\n"); fprintf(stderr, "\t--job-fence test fence inside its own namespace.\n"); fprintf(stderr, "\t-c relative to the --job-fence option: fence[_nb] callback shall include all collected data\n"); fprintf(stderr, "\t-nb relative to the --job-fence option: use non-blocking fence\n"); fprintf(stderr, "\t--noise \"[ns0:ranks;ns1:ranks...]\" add system noise to specified processes.\n"); fprintf(stderr, "\t--test-publish test publish/lookup/unpublish api.\n"); fprintf(stderr, "\t--test-spawn test spawn api.\n"); fprintf(stderr, "\t--test-connect test connect/disconnect api.\n"); fprintf(stderr, "\t--test-resolve-peers test resolve_peers api.\n"); exit(0); } else if (0 == strcmp(argv[i], "--exec") || 0 == strcmp(argv[i], "-e")) { i++; if (NULL != argv[i]) { params->binary = strdup(argv[i]); } } else if( 0 == strcmp(argv[i], "--verbose") || 0 == strcmp(argv[i],"-v") ){ TEST_VERBOSE_ON(); params->verbose = 1; } else if (0 == strcmp(argv[i], "--timeout") || 0 == strcmp(argv[i], "-t")) { i++; if (NULL != argv[i]) { params->timeout = atoi(argv[i]); if( params->timeout == 0 ){ params->timeout = TEST_DEFAULT_TIMEOUT; } } } else if( 0 == strcmp(argv[i], "-o")) { i++; if (NULL != argv[i]) { params->prefix = strdup(argv[i]); } } else if( 0 == strcmp(argv[i], "-s")) { i++; if (NULL != argv[i]) { params->nspace = strdup(argv[i]); } } else if (0 == strcmp(argv[i], "--rank") || 0 == strcmp(argv[i], "-r")) { i++; if (NULL != argv[i]) { params->rank = strtol(argv[i], NULL, 10); } } else if( 0 == strcmp(argv[i], "--early-fail") ){ params->early_fail = 1; } else if (0 == strcmp(argv[i], "--fence")) { i++; if (NULL != argv[i]) { params->fences = strdup(argv[i]); if (0 != parse_fence(params->fences, 0)) { fprintf(stderr, "Incorrect --fence option format: %s\n", params->fences); exit(1); } } } else if (0 == strcmp(argv[i], "--use-same-keys")) { params->use_same_keys = 1; } else if (0 == strcmp(argv[i], "--job-fence")) { params->test_job_fence = 1; } else if (0 == strcmp(argv[i], "--collect-corrupt")) { params->collect_bad = 1; } else if (0 == strcmp(argv[i], "--collect") || 0 == strcmp(argv[i], "-c")) { params->collect = 1; } else if (0 == strcmp(argv[i], "--non-blocking") || 0 == strcmp(argv[i], "-nb")) { params->nonblocking = 1; } else if (0 == strcmp(argv[i], "--noise")) { i++; if (NULL != argv[i]) { params->noise = strdup(argv[i]); if (0 != parse_noise(params->noise, 0)) { fprintf(stderr, "Incorrect --noise option format: %s\n", params->noise); exit(1); } } } else if (0 == strcmp(argv[i], "--ns-dist")) { i++; if (NULL != argv[i]) { params->ns_dist = strdup(argv[i]); } } else if (0 == strcmp(argv[i], "--ns-size")) { i++; if (NULL != argv[i]) { params->ns_size = strtol(argv[i], NULL, 10); } } else if (0 == strcmp(argv[i], "--ns-id")) { i++; if (NULL != argv[i]) { params->ns_id = strtol(argv[i], NULL, 10); } } else if (0 == strcmp(argv[i], "--base-rank")) { i++; if (NULL != argv[i]) { params->base_rank = strtol(argv[i], NULL, 10); } } else if( 0 == strcmp(argv[i], "--test-publish") ){ params->test_publish = 1; } else if( 0 == strcmp(argv[i], "--test-spawn") ){ params->test_spawn = 1; } else if( 0 == strcmp(argv[i], "--test-connect") ){ params->test_connect = 1; } else if( 0 == strcmp(argv[i], "--test-resolve-peers") ){ params->test_resolve_peers = 1; } else { fprintf(stderr, "unrecognized option: %s\n", argv[i]); exit(1); } } if (NULL == params->binary) { char *basename = NULL; basename = strrchr(argv[0], '/'); if (basename) { *basename = '\0'; /* pmix_test and pmix_clients are the shell scripts that * make sure that actual binary placed in "./.libs" directory * is properly linked. * after launch pmix_test you'll find the following process: * <pmix-root-dir>/test/.libs/lt-pmix_test * * To launch * <pmix-root-dir>/test/pmix_client * instead of * <pmix-root-dir>/test/.libs/pmix_client * we need to do a step back in directory tree. */ asprintf(¶ms->binary, "%s/../pmix_client", argv[0]); *basename = '/'; } else { asprintf(¶ms->binary, "pmix_client"); } } if( params->collect_bad ){ params->collect = params->rank % 2; } // Fix rank if running under SLURM if( 0 > params->rank ){ char *ranklist = getenv("SLURM_GTIDS"); char *rankno = getenv("SLURM_LOCALID"); if( NULL != ranklist && NULL != rankno ){ char **argv = pmix_argv_split(ranklist, ','); int count = pmix_argv_count(argv); int rankidx = strtoul(rankno, NULL, 10); if( rankidx >= count ){ fprintf(stderr, "It feels like we are running under SLURM:\n\t" "SLURM_GTIDS=%s, SLURM_LOCALID=%s\nbut env vars are conflicting\n", ranklist, rankno); exit(1); } params->rank = strtoul(argv[rankidx], NULL, 10); pmix_argv_free(argv); } } // Fix namespace if running under SLURM if( NULL == params->nspace ){ char *nspace = getenv("PMIX_NAMESPACE"); if( NULL != nspace ){ params->nspace = strdup(nspace); } } }
/* * Scan all the files in a directory (or path) and invoke a callback * on each one. */ static int pdlopen_foreachfile(const char *search_path, int (*func)(const char *filename, void *data), void *data) { int ret; DIR *dp = NULL; char **dirs = NULL; char **good_files = NULL; dirs = pmix_argv_split(search_path, PMIX_ENV_SEP); for (int i = 0; NULL != dirs && NULL != dirs[i]; ++i) { dp = opendir(dirs[i]); if (NULL == dp) { ret = PMIX_ERR_IN_ERRNO; goto error; } struct dirent *de; while (NULL != (de = readdir(dp))) { /* Make the absolute path name */ char *abs_name = NULL; ret = asprintf(&abs_name, "%s/%s", dirs[i], de->d_name); if (0 > ret) { return PMIX_ERR_NOMEM; } if (NULL == abs_name) { ret = PMIX_ERR_IN_ERRNO; goto error; } /* Stat the file */ struct stat buf; if (stat(abs_name, &buf) < 0) { free(abs_name); ret = PMIX_ERR_IN_ERRNO; goto error; } /* Skip if not a file */ if (!S_ISREG(buf.st_mode)) { free(abs_name); continue; } /* Find the suffix */ char *ptr = strrchr(abs_name, '.'); if (NULL != ptr) { /* Skip libtool files */ if (strcmp(ptr, ".la") == 0 || strcmp(ptr, ".lo") == 0) { free (abs_name); continue; } *ptr = '\0'; } /* Have we already found this file? Or already found a file with the same basename (but different suffix)? */ bool found = false; for (int j = 0; NULL != good_files && NULL != good_files[j]; ++j) { if (strcmp(good_files[j], abs_name) == 0) { found = true; break; } } if (!found) { pmix_argv_append_nosize(&good_files, abs_name); } free(abs_name); } closedir(dp); } dp = NULL; /* Invoke the callback on all the found files */ if (NULL != good_files) { for (int i = 0; NULL != good_files[i]; ++i) { ret = func(good_files[i], data); if (PMIX_SUCCESS != ret) { goto error; } } } ret = PMIX_SUCCESS; error: if (NULL != dp) { closedir(dp); } if (NULL != dirs) { pmix_argv_free(dirs); } if (NULL != good_files) { pmix_argv_free(good_files); } return ret; }