static void lookup_cbfunc(pmix_status_t status, pmix_pdata_t pdata[], size_t ndata, void *cbdata) { pmix_cb_t *cb = (pmix_cb_t*)cbdata; pmix_pdata_t *tgt = (pmix_pdata_t*)cb->cbdata; size_t i, j; PMIX_ACQUIRE_OBJECT(cb); cb->status = status; if (PMIX_SUCCESS == status) { /* find the matching key in the provided info array - error if not found */ for (i=0; i < ndata; i++) { for (j=0; j < cb->nvals; j++) { if (0 == strcmp(pdata[i].key, tgt[j].key)) { /* transfer the publishing proc id */ (void)strncpy(tgt[j].proc.nspace, pdata[i].proc.nspace, PMIX_MAX_NSLEN); tgt[j].proc.rank = pdata[i].proc.rank; /* transfer the value to the pmix_info_t */ PMIX_BFROPS_VALUE_XFER(cb->status, pmix_client_globals.myserver, &tgt[j].value, &pdata[i].value); break; } } } } PMIX_POST_OBJECT(cb); PMIX_WAKEUP_THREAD(&cb->lock); }
static void pmix_usock_send(int sd, short args, void *cbdata) { pmix_ptl_queue_t *queue = (pmix_ptl_queue_t*)cbdata; pmix_ptl_send_t *snd; /* acquire the object */ PMIX_ACQUIRE_OBJECT(queue); if (NULL == queue->peer || queue->peer->sd < 0 || NULL == queue->peer->info || NULL == queue->peer->nptr) { /* this peer has lost connection */ PMIX_RELEASE(queue); /* ensure we post the object before another thread * picks it back up */ PMIX_POST_OBJECT(queue); return; } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "[%s:%d] send to %s:%u on tag %d", __FILE__, __LINE__, (queue->peer)->info->pname.nspace, (queue->peer)->info->pname.rank, (queue->tag)); snd = PMIX_NEW(pmix_ptl_send_t); snd->hdr.pindex = htonl(pmix_globals.pindex); snd->hdr.tag = htonl(queue->tag); snd->hdr.nbytes = htonl((queue->buf)->bytes_used); snd->data = (queue->buf); /* always start with the header */ snd->sdptr = (char*)&snd->hdr; snd->sdbytes = sizeof(pmix_ptl_hdr_t); /* if there is no message on-deck, put this one there */ if (NULL == (queue->peer)->send_msg) { (queue->peer)->send_msg = snd; } else { /* add it to the queue */ pmix_list_append(&(queue->peer)->send_queue, &snd->super); } /* ensure the send event is active */ if (!(queue->peer)->send_ev_active) { (queue->peer)->send_ev_active = true; PMIX_POST_OBJECT(queue->peer); pmix_event_add(&(queue->peer)->send_event, 0); } PMIX_RELEASE(queue); PMIX_POST_OBJECT(snd); }
static void wait_cbfunc(struct pmix_peer_t *pr, pmix_ptl_hdr_t *hdr, pmix_buffer_t *buf, void *cbdata) { pmix_cb_t *cb = (pmix_cb_t*)cbdata; pmix_status_t rc; int ret; int32_t cnt; PMIX_ACQUIRE_OBJECT(cb); pmix_output_verbose(2, pmix_globals.debug_output, "pmix:client recv callback activated with %d bytes", (NULL == buf) ? -1 : (int)buf->bytes_used); if (NULL == buf) { rc = PMIX_ERR_BAD_PARAM; goto report; } /* a zero-byte buffer indicates that this recv is being * completed due to a lost connection */ if (PMIX_BUFFER_IS_EMPTY(buf)) { rc = PMIX_ERR_UNREACH; goto report; } /* unpack the returned status */ cnt = 1; PMIX_BFROPS_UNPACK(rc, pmix_client_globals.myserver, buf, &ret, &cnt, PMIX_STATUS); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); } report: if (NULL != cb->cbfunc.opfn) { cb->cbfunc.opfn(rc, cb->cbdata); } PMIX_RELEASE(cb); }
void pmix_usock_send_recv(int fd, short args, void *cbdata) { pmix_ptl_sr_t *ms = (pmix_ptl_sr_t*)cbdata; pmix_ptl_posted_recv_t *req; pmix_ptl_send_t *snd; uint32_t tag; /* acquire the object */ PMIX_ACQUIRE_OBJECT(ms); if (ms->peer->sd < 0) { /* this peer's socket has been closed */ PMIX_RELEASE(ms); /* ensure we post the object before another thread * picks it back up */ PMIX_POST_OBJECT(NULL); return; } /* take the next tag in the sequence */ pmix_ptl_globals.current_tag++; if (UINT32_MAX == pmix_ptl_globals.current_tag ) { pmix_ptl_globals.current_tag = PMIX_PTL_TAG_DYNAMIC; } tag = pmix_ptl_globals.current_tag; if (NULL != ms->cbfunc) { /* if a callback msg is expected, setup a recv for it */ req = PMIX_NEW(pmix_ptl_posted_recv_t); req->tag = tag; req->cbfunc = ms->cbfunc; req->cbdata = ms->cbdata; pmix_output_verbose(5, pmix_ptl_base_framework.framework_output, "posting recv on tag %d", req->tag); /* add it to the list of recvs - we cannot have unexpected messages * in this subsystem as the server never sends us something that * we didn't previously request */ pmix_list_prepend(&pmix_ptl_globals.posted_recvs, &req->super); } snd = PMIX_NEW(pmix_ptl_send_t); snd->hdr.pindex = pmix_globals.pindex; snd->hdr.tag = tag; snd->hdr.nbytes = ms->bfr->bytes_used; snd->data = ms->bfr; /* always start with the header */ snd->sdptr = (char*)&snd->hdr; snd->sdbytes = sizeof(pmix_usock_hdr_t); /* if there is no message on-deck, put this one there */ if (NULL == ms->peer->send_msg) { ms->peer->send_msg = snd; } else { /* add it to the queue */ pmix_list_append(&ms->peer->send_queue, &snd->super); } /* ensure the send event is active */ if (!ms->peer->send_ev_active) { ms->peer->send_ev_active = true; PMIX_POST_OBJECT(snd); pmix_event_add(&ms->peer->send_event, 0); } /* cleanup */ PMIX_RELEASE(ms); PMIX_POST_OBJECT(snd); }
void pmix_usock_recv_handler(int sd, short flags, void *cbdata) { pmix_status_t rc; pmix_peer_t *peer = (pmix_peer_t*)cbdata; pmix_ptl_recv_t *msg = NULL; /* acquire the object */ PMIX_ACQUIRE_OBJECT(peer); pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:recv:handler called with peer %s:%d", (NULL == peer) ? "NULL" : peer->info->pname.nspace, (NULL == peer) ? PMIX_RANK_UNDEF : peer->info->pname.rank); if (NULL == peer) { return; } /* allocate a new message and setup for recv */ if (NULL == peer->recv_msg) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:recv:handler allocate new recv msg"); peer->recv_msg = PMIX_NEW(pmix_ptl_recv_t); if (NULL == peer->recv_msg) { pmix_output(0, "usock_recv_handler: unable to allocate recv message\n"); goto err_close; } PMIX_RETAIN(peer); peer->recv_msg->peer = peer; // provide a handle back to the peer object /* start by reading the header */ peer->recv_msg->rdptr = (char*)&peer->recv_msg->hdr; peer->recv_msg->rdbytes = sizeof(pmix_usock_hdr_t); } msg = peer->recv_msg; msg->sd = sd; /* if the header hasn't been completely read, read it */ if (!msg->hdr_recvd) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:recv:handler read hdr on socket %d", peer->sd); if (PMIX_SUCCESS == (rc = read_bytes(peer->sd, &msg->rdptr, &msg->rdbytes))) { /* completed reading the header */ peer->recv_msg->hdr_recvd = true; pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "RECVD MSG FOR TAG %d SIZE %d", (int)peer->recv_msg->hdr.tag, (int)peer->recv_msg->hdr.nbytes); /* if this is a zero-byte message, then we are done */ if (0 == peer->recv_msg->hdr.nbytes) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "RECVD ZERO-BYTE MESSAGE FROM %s:%d for tag %d", peer->info->pname.nspace, peer->info->pname.rank, peer->recv_msg->hdr.tag); peer->recv_msg->data = NULL; // make sure peer->recv_msg->rdptr = NULL; peer->recv_msg->rdbytes = 0; /* post it for delivery */ PMIX_ACTIVATE_POST_MSG(peer->recv_msg); peer->recv_msg = NULL; PMIX_POST_OBJECT(peer); return; } else { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:recv:handler allocate data region of size %lu", (unsigned long)peer->recv_msg->hdr.nbytes); /* allocate the data region */ peer->recv_msg->data = (char*)malloc(peer->recv_msg->hdr.nbytes); memset(peer->recv_msg->data, 0, peer->recv_msg->hdr.nbytes); /* point to it */ peer->recv_msg->rdptr = peer->recv_msg->data; peer->recv_msg->rdbytes = peer->recv_msg->hdr.nbytes; } /* fall thru and attempt to read the data */ } else if (PMIX_ERR_RESOURCE_BUSY == rc || PMIX_ERR_WOULD_BLOCK == rc) { /* exit this event and let the event lib progress */ return; } else { /* the remote peer closed the connection - report that condition * and let the caller know */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix_usock_msg_recv: peer closed connection"); goto err_close; } } if (peer->recv_msg->hdr_recvd) { /* continue to read the data block - we start from * wherever we left off, which could be at the * beginning or somewhere in the message */ if (PMIX_SUCCESS == (rc = read_bytes(peer->sd, &msg->rdptr, &msg->rdbytes))) { /* we recvd all of the message */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "RECVD COMPLETE MESSAGE FROM SERVER OF %d BYTES FOR TAG %d ON PEER SOCKET %d", (int)peer->recv_msg->hdr.nbytes, peer->recv_msg->hdr.tag, peer->sd); /* post it for delivery */ PMIX_ACTIVATE_POST_MSG(peer->recv_msg); peer->recv_msg = NULL; /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); return; } else if (PMIX_ERR_RESOURCE_BUSY == rc || PMIX_ERR_WOULD_BLOCK == rc) { /* exit this event and let the event lib progress */ /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); return; } else { /* the remote peer closed the connection - report that condition * and let the caller know */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "pmix_usock_msg_recv: peer closed connection"); goto err_close; } } /* success */ return; err_close: /* stop all events */ if (peer->recv_ev_active) { pmix_event_del(&peer->recv_event); peer->recv_ev_active = false; } if (peer->send_ev_active) { pmix_event_del(&peer->send_event); peer->send_ev_active = false; } if (NULL != peer->recv_msg) { PMIX_RELEASE(peer->recv_msg); peer->recv_msg = NULL; } pmix_ptl_base_lost_connection(peer, PMIX_ERR_UNREACH); /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); }
/* * A file descriptor is available/ready for send. Check the state * of the socket and take the appropriate action. */ void pmix_usock_send_handler(int sd, short flags, void *cbdata) { pmix_peer_t *peer = (pmix_peer_t*)cbdata; pmix_ptl_send_t *msg = peer->send_msg; pmix_status_t rc; uint32_t nbytes; /* acquire the object */ PMIX_ACQUIRE_OBJECT(peer); pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "%s:%d usock:send_handler SENDING TO PEER %s:%d tag %u with %s msg", pmix_globals.myid.nspace, pmix_globals.myid.rank, peer->info->pname.nspace, peer->info->pname.rank, (NULL == msg) ? UINT_MAX : msg->hdr.tag, (NULL == msg) ? "NULL" : "NON-NULL"); if (NULL != msg) { if (!msg->hdr_sent) { if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) { /* we have to convert the header back to host-byte order */ msg->hdr.pindex = ntohl(msg->hdr.pindex); msg->hdr.tag = ntohl(msg->hdr.tag); nbytes = msg->hdr.nbytes; msg->hdr.nbytes = ntohl(nbytes); } pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:send_handler SENDING HEADER WITH MSG IDX %d TAG %d SIZE %lu", msg->hdr.pindex, msg->hdr.tag, (unsigned long)msg->hdr.nbytes); if (PMIX_SUCCESS == (rc = send_bytes(peer->sd, &msg->sdptr, &msg->sdbytes))) { /* header is completely sent */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:send_handler HEADER SENT"); msg->hdr_sent = true; /* setup to send the data */ if (NULL == msg->data) { /* this was a zero-byte msg - nothing more to do */ PMIX_RELEASE(msg); peer->send_msg = NULL; goto next; } else { /* send the data as a single block */ msg->sdptr = msg->data->base_ptr; msg->sdbytes = msg->hdr.nbytes; } /* fall thru and let the send progress */ } else if (PMIX_ERR_RESOURCE_BUSY == rc || PMIX_ERR_WOULD_BLOCK == rc) { /* exit this event and let the event lib progress */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:send_handler RES BUSY OR WOULD BLOCK"); if (PMIX_PROC_IS_SERVER(pmix_globals.mypeer)) { /* have to convert back again so we are correct when we re-enter */ msg->hdr.pindex = htonl(msg->hdr.pindex); msg->hdr.tag = htonl(msg->hdr.tag); nbytes = msg->hdr.nbytes; msg->hdr.nbytes = htonl(nbytes); } /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); return; } else { // report the error event_del(&peer->send_event); peer->send_ev_active = false; PMIX_RELEASE(msg); peer->send_msg = NULL; pmix_ptl_base_lost_connection(peer, rc); /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); return; } } if (msg->hdr_sent) { pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:send_handler SENDING BODY OF MSG"); if (PMIX_SUCCESS == (rc = send_bytes(peer->sd, &msg->sdptr, &msg->sdbytes))) { // message is complete pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:send_handler BODY SENT"); PMIX_RELEASE(msg); peer->send_msg = NULL; } else if (PMIX_ERR_RESOURCE_BUSY == rc || PMIX_ERR_WOULD_BLOCK == rc) { /* exit this event and let the event lib progress */ pmix_output_verbose(2, pmix_ptl_base_framework.framework_output, "usock:send_handler RES BUSY OR WOULD BLOCK"); /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); return; } else { // report the error pmix_output(0, "pmix_usock_peer_send_handler: unable to send message ON SOCKET %d", peer->sd); pmix_event_del(&peer->send_event); peer->send_ev_active = false; PMIX_RELEASE(msg); peer->send_msg = NULL; pmix_ptl_base_lost_connection(peer, rc); /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); return; } } next: /* if current message completed - progress any pending sends by * moving the next in the queue into the "on-deck" position. Note * that this doesn't mean we send the message right now - we will * wait for another send_event to fire before doing so. This gives * us a chance to service any pending recvs. */ peer->send_msg = (pmix_ptl_send_t*) pmix_list_remove_first(&peer->send_queue); } /* if nothing else to do unregister for send event notifications */ if (NULL == peer->send_msg && peer->send_ev_active) { pmix_event_del(&peer->send_event); peer->send_ev_active = false; } /* ensure we post the modified peer object before another thread * picks it back up */ PMIX_POST_OBJECT(peer); }
static void wait_lookup_cbfunc(struct pmix_peer_t *pr, pmix_ptl_hdr_t *hdr, pmix_buffer_t *buf, void *cbdata) { pmix_cb_t *cb = (pmix_cb_t*)cbdata; pmix_status_t rc, ret; int32_t cnt; pmix_pdata_t *pdata; size_t ndata; PMIX_ACQUIRE_OBJECT(cb); pmix_output_verbose(2, pmix_globals.debug_output, "pmix:client recv callback activated with %d bytes", (NULL == buf) ? -1 : (int)buf->bytes_used); /* set the defaults */ pdata = NULL; ndata = 0; if (NULL == cb->cbfunc.lookupfn) { /* nothing we can do with this */ PMIX_RELEASE(cb); return; } if (NULL == buf) { rc = PMIX_ERR_BAD_PARAM; goto report; } /* a zero-byte buffer indicates that this recv is being * completed due to a lost connection */ if (PMIX_BUFFER_IS_EMPTY(buf)) { rc = PMIX_ERR_UNREACH; goto report; } /* unpack the returned status */ cnt = 1; PMIX_BFROPS_UNPACK(rc, pmix_client_globals.myserver, buf, &ret, &cnt, PMIX_STATUS); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); ret = rc; } if (PMIX_SUCCESS != ret) { if (NULL != cb->cbfunc.lookupfn) { cb->cbfunc.lookupfn(ret, NULL, 0, cb->cbdata); } PMIX_RELEASE(cb); return; } /* unpack the number of returned values */ cnt = 1; PMIX_BFROPS_UNPACK(rc, pmix_client_globals.myserver, buf, &ndata, &cnt, PMIX_SIZE); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); PMIX_RELEASE(cb); return; } if (0 < ndata) { /* create the array storage */ PMIX_PDATA_CREATE(pdata, ndata); cnt = ndata; /* unpack the returned values into the pdata array */ PMIX_BFROPS_UNPACK(rc, pmix_client_globals.myserver, buf, pdata, &cnt, PMIX_PDATA); if (PMIX_SUCCESS != rc) { PMIX_ERROR_LOG(rc); goto cleanup; } } report: if (NULL != cb->cbfunc.lookupfn) { cb->cbfunc.lookupfn(rc, pdata, ndata, cb->cbdata); } cleanup: /* cleanup */ if (NULL != pdata) { PMIX_PDATA_FREE(pdata, ndata); } PMIX_RELEASE(cb); }