Example #1
0
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);
}
Example #2
0
void pmix_usock_recv_handler(int sd, short flags, void *cbdata)
{
    int rc;

    opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                        "%s usock:recv:handler called",
                        OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));

    switch (mca_pmix_native_component.state) {
    case PMIX_USOCK_CONNECT_ACK:
        if (OPAL_SUCCESS == (rc = usock_recv_connect_ack())) {
            opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                "%s usock:recv:handler starting send/recv events",
                                OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
            /* we connected! Start the send/recv events */
            if (!mca_pmix_native_component.recv_ev_active) {
                opal_event_add(&mca_pmix_native_component.recv_event, 0);
                mca_pmix_native_component.recv_ev_active = true;
            }
            if (mca_pmix_native_component.timer_ev_active) {
                opal_event_del(&mca_pmix_native_component.timer_event);
                mca_pmix_native_component.timer_ev_active = false;
            }
            /* if there is a message waiting to be sent, queue it */
            if (NULL == mca_pmix_native_component.send_msg) {
                mca_pmix_native_component.send_msg = (pmix_usock_send_t*)opal_list_remove_first(&mca_pmix_native_component.send_queue);
            }
            if (NULL != mca_pmix_native_component.send_msg && !mca_pmix_native_component.send_ev_active) {
                opal_event_add(&mca_pmix_native_component.send_event, 0);
                mca_pmix_native_component.send_ev_active = true;
            }
            /* update our state */
            mca_pmix_native_component.state = PMIX_USOCK_CONNECTED;
        } else {
            opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                "%s UNABLE TO COMPLETE CONNECT ACK WITH SERVER",
                                OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
            opal_event_del(&mca_pmix_native_component.recv_event);
            mca_pmix_native_component.recv_ev_active = false;
            return;
        }
        break;
    case PMIX_USOCK_CONNECTED:
        opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                            "%s usock:recv:handler CONNECTED",
                            OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
        /* allocate a new message and setup for recv */
        if (NULL == mca_pmix_native_component.recv_msg) {
            opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                "%s usock:recv:handler allocate new recv msg",
                                OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
            mca_pmix_native_component.recv_msg = OBJ_NEW(pmix_usock_recv_t);
            if (NULL == mca_pmix_native_component.recv_msg) {
                opal_output(0, "%s usock_recv_handler: unable to allocate recv message\n",
                            OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
                return;
            }
            /* start by reading the header */
            mca_pmix_native_component.recv_msg->rdptr = (char*)&mca_pmix_native_component.recv_msg->hdr;
            mca_pmix_native_component.recv_msg->rdbytes = sizeof(pmix_usock_hdr_t);
        }
        /* if the header hasn't been completely read, read it */
        if (!mca_pmix_native_component.recv_msg->hdr_recvd) {
            opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                "usock:recv:handler read hdr");
            if (OPAL_SUCCESS == (rc = read_bytes(mca_pmix_native_component.recv_msg))) {
                /* completed reading the header */
                mca_pmix_native_component.recv_msg->hdr_recvd = true;
                /* if this is a zero-byte message, then we are done */
                if (0 == mca_pmix_native_component.recv_msg->hdr.nbytes) {
                    opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                        "%s RECVD ZERO-BYTE MESSAGE FROM SERVER for tag %d",
                                        OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
                                        mca_pmix_native_component.recv_msg->hdr.tag);
                    mca_pmix_native_component.recv_msg->data = NULL;  // make sure
                    mca_pmix_native_component.recv_msg->rdptr = NULL;
                    mca_pmix_native_component.recv_msg->rdbytes = 0;
                } else {
                    opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                        "%s usock:recv:handler allocate data region of size %lu",
                                        OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
                                        (unsigned long)mca_pmix_native_component.recv_msg->hdr.nbytes);
                    /* allocate the data region */
                    mca_pmix_native_component.recv_msg->data = (char*)malloc(mca_pmix_native_component.recv_msg->hdr.nbytes);
                    /* point to it */
                    mca_pmix_native_component.recv_msg->rdptr = mca_pmix_native_component.recv_msg->data;
                    mca_pmix_native_component.recv_msg->rdbytes = mca_pmix_native_component.recv_msg->hdr.nbytes;
                }
                /* fall thru and attempt to read the data */
            } else if (OPAL_ERR_RESOURCE_BUSY == rc ||
                       OPAL_ERR_WOULD_BLOCK == rc) {
                /* exit this event and let the event lib progress */
                return;
            } else {
                /* close the connection */
                opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                    "%s usock:recv:handler error reading bytes - closing connection",
                                    OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
                CLOSE_THE_SOCKET(mca_pmix_native_component.sd);
                return;
            }
        }

        if (mca_pmix_native_component.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 (OPAL_SUCCESS == (rc = read_bytes(mca_pmix_native_component.recv_msg))) {
                /* we recvd all of the message */
                opal_output_verbose(2, opal_pmix_base_framework.framework_output,
                                    "%s RECVD COMPLETE MESSAGE FROM SERVER OF %d BYTES FOR TAG %d",
                                    OPAL_NAME_PRINT(OPAL_PROC_MY_NAME),
                                    (int)mca_pmix_native_component.recv_msg->hdr.nbytes,
                                    mca_pmix_native_component.recv_msg->hdr.tag);
                /* post it for delivery */
                PMIX_ACTIVATE_POST_MSG(mca_pmix_native_component.recv_msg);
                mca_pmix_native_component.recv_msg = NULL;
            } else if (OPAL_ERR_RESOURCE_BUSY == rc ||
                       OPAL_ERR_WOULD_BLOCK == rc) {
                /* exit this event and let the event lib progress */
                return;
            } else {
                // report the error
                opal_output(0, "%s usock_peer_recv_handler: unable to recv message",
                            OPAL_NAME_PRINT(OPAL_PROC_MY_NAME));
                /* turn off the recv event */
                opal_event_del(&mca_pmix_native_component.recv_event);
                mca_pmix_native_component.recv_ev_active = false;
                CLOSE_THE_SOCKET(mca_pmix_native_component.sd);
                return;
            }
        }
        break;
    default: 
        opal_output(0, "%s usock_peer_recv_handler: invalid socket state(%d)",
                    OPAL_NAME_PRINT(OPAL_PROC_MY_NAME), 
                    mca_pmix_native_component.state);
        CLOSE_THE_SOCKET(mca_pmix_native_component.sd);
        break;
    }
}