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; }
PMIX_EXPORT pmix_status_t PMIx_Fence(const pmix_proc_t procs[], size_t nprocs, const pmix_info_t info[], size_t ninfo) { pmix_cb_t *cb; pmix_status_t rc; PMIX_ACQUIRE_THREAD(&pmix_global_lock); pmix_output_verbose(2, pmix_globals.debug_output, "pmix: executing fence"); 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); /* 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); /* push the message into our event base to send to the server */ if (PMIX_SUCCESS != (rc = PMIx_Fence_nb(procs, nprocs, info, ninfo, op_cbfunc, cb))) { PMIX_ERROR_LOG(rc); PMIX_RELEASE(cb); return rc; } /* wait for the fence to complete */ PMIX_WAIT_THREAD(&cb->lock); rc = cb->status; PMIX_RELEASE(cb); pmix_output_verbose(2, pmix_globals.debug_output, "pmix: fence released"); return rc; }
PMIX_EXPORT pmix_status_t PMIx_Unpublish(char **keys, const pmix_info_t info[], size_t ninfo) { pmix_status_t rc; pmix_cb_t *cb; PMIX_ACQUIRE_THREAD(&pmix_global_lock); pmix_output_verbose(2, pmix_globals.debug_output, "pmix: unpublish 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); /* 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); /* push the message into our event base to send to the server */ if (PMIX_SUCCESS != (rc = PMIx_Unpublish_nb(keys, info, ninfo, op_cbfunc, cb))) { PMIX_RELEASE(cb); return rc; } /* wait for the server to ack our request */ PMIX_WAIT_THREAD(&cb->lock); rc = cb->status; PMIX_RELEASE(cb); return rc; }
PMIX_EXPORT pmix_status_t PMIx_Publish(const pmix_info_t info[], size_t ninfo) { pmix_status_t rc; pmix_cb_t *cb; PMIX_ACQUIRE_THREAD(&pmix_global_lock); pmix_output_verbose(2, pmix_globals.debug_output, "pmix: publish 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); /* create a callback object to let us know when it is done */ cb = PMIX_NEW(pmix_cb_t); if (PMIX_SUCCESS != (rc = PMIx_Publish_nb(info, ninfo, op_cbfunc, cb))) { PMIX_ERROR_LOG(rc); PMIX_RELEASE(cb); return rc; } /* wait for the server to ack our request */ PMIX_WAIT_THREAD(&cb->lock); rc = (pmix_status_t)cb->status; PMIX_RELEASE(cb); return rc; }
PMIX_EXPORT pmix_status_t PMIx_Allocation_request(pmix_alloc_directive_t directive, pmix_info_t *info, size_t ninfo) { pmix_cb_t cb; pmix_status_t rc; PMIX_ACQUIRE_THREAD(&pmix_global_lock); if (pmix_globals.init_cntr <= 0) { PMIX_RELEASE_THREAD(&pmix_global_lock); return PMIX_ERR_INIT; } PMIX_RELEASE_THREAD(&pmix_global_lock); pmix_output_verbose(2, pmix_globals.debug_output, "%s pmix:allocate", PMIX_NAME_PRINT(&pmix_globals.myid)); /* 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 */ PMIX_CONSTRUCT(&cb, pmix_cb_t); if (PMIX_SUCCESS != (rc = PMIx_Allocation_request_nb(directive, info, ninfo, acb, &cb))) { PMIX_DESTRUCT(&cb); return rc; } /* wait for the operation to complete */ PMIX_WAIT_THREAD(&cb.lock); rc = cb.status; PMIX_DESTRUCT(&cb); pmix_output_verbose(2, pmix_globals.debug_output, "pmix:allocate completed"); return rc; }
PMIX_EXPORT pmix_status_t PMIx_Log(const pmix_info_t data[], size_t ndata, const pmix_info_t directives[], size_t ndirs) { pmix_cb_t cb; pmix_status_t rc; PMIX_ACQUIRE_THREAD(&pmix_global_lock); if (pmix_globals.init_cntr <= 0) { PMIX_RELEASE_THREAD(&pmix_global_lock); return PMIX_ERR_INIT; } PMIX_RELEASE_THREAD(&pmix_global_lock); pmix_output_verbose(2, pmix_plog_base_framework.framework_output, "%s pmix:log", PMIX_NAME_PRINT(&pmix_globals.myid)); /* 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 */ PMIX_CONSTRUCT(&cb, pmix_cb_t); if (PMIX_SUCCESS != (rc = PMIx_Log_nb(data, ndata, directives, ndirs, opcbfunc, &cb))) { PMIX_DESTRUCT(&cb); return rc; } /* wait for the operation to complete */ PMIX_WAIT_THREAD(&cb.lock); rc = cb.status; PMIX_DESTRUCT(&cb); pmix_output_verbose(2, pmix_plog_base_framework.framework_output, "pmix:log completed"); return rc; }
/**** SUPPORTING FUNCTIONS ****/ static pmix_status_t parse_uri_file(char *filename, char **uri, char **nspace, pmix_rank_t *rank) { FILE *fp; char *srvr, *p, *p2; pmix_lock_t lock; pmix_event_t ev; struct timeval tv; int retries; fp = fopen(filename, "r"); if (NULL == fp) { /* if we cannot open the file, then the server must not * be configured to support tool connections, or this * user isn't authorized to access it - or it may just * not exist yet! Check for existence */ if (0 != access(filename, R_OK)) { if (ENOENT == errno && 0 < mca_ptl_tcp_component.wait_to_connect) { /* the file does not exist, so give it * a little time to see if the server * is still starting up */ retries = 0; do { ++retries; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "WAITING FOR CONNECTION FILE"); PMIX_CONSTRUCT_LOCK(&lock); tv.tv_sec = mca_ptl_tcp_component.wait_to_connect; tv.tv_usec = 0; pmix_event_evtimer_set(pmix_globals.evbase, &ev, timeout, &lock); pmix_event_evtimer_add(&ev, &tv); PMIX_WAIT_THREAD(&lock); PMIX_DESTRUCT_LOCK(&lock); fp = fopen(filename, "r"); if (NULL != fp) { /* we found it! */ goto process; } } while (retries < mca_ptl_tcp_component.max_retries); /* otherwise, mark it as unreachable */ } } return PMIX_ERR_UNREACH; } process: /* get the URI */ srvr = pmix_getline(fp); if (NULL == srvr) { PMIX_ERROR_LOG(PMIX_ERR_FILE_READ_FAILURE); fclose(fp); return PMIX_ERR_UNREACH; } /* see if this file contains the server's version */ p2 = pmix_getline(fp); if (NULL == p2) { 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"); pmix_client_globals.myserver->protocol = PMIX_PROTOCOL_V2; } else if (0 == strncmp(p2, "v2.1", strlen("v2.1")) || 0 == strncmp(p2, "2.1", strlen("2.1"))) { pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V21; pmix_client_globals.myserver->protocol = PMIX_PROTOCOL_V2; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "V21 SERVER DETECTED"); } else if (0 == strncmp(p2, "3", strlen("3")) || 0 == strncmp(p2, "v3", strlen("v3"))) { pmix_client_globals.myserver->proc_type = PMIX_PROC_SERVER | PMIX_PROC_V3; pmix_client_globals.myserver->protocol = PMIX_PROTOCOL_V2; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "V3 SERVER DETECTED"); } else { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "UNKNOWN SERVER VERSION DETECTED: %s", p2); } if (NULL != p2) { free(p2); } 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/rank */ *nspace = strdup(srvr); *rank = strtoull(p2, NULL, 10); /* now parse the uri itself */ *uri = strdup(p); free(srvr); return PMIX_SUCCESS; }