btl_tcp_endpoint.c

来自「MPI stands for the Message Passing Inter」· C语言 代码 · 共 714 行 · 第 1/2 页

C
714
字号
        btl_endpoint->endpoint_cache_length = 0;#endif  /* MCA_BTL_TCP_ENDPOINT_CACHE */    }    btl_endpoint->endpoint_state = MCA_BTL_TCP_CLOSED;    btl_endpoint->endpoint_retries++;}void mca_btl_tcp_endpoint_shutdown(mca_btl_base_endpoint_t* btl_endpoint){    OPAL_THREAD_LOCK(&btl_endpoint->endpoint_recv_lock);    OPAL_THREAD_LOCK(&btl_endpoint->endpoint_send_lock);    mca_btl_tcp_endpoint_close(btl_endpoint);    btl_endpoint->endpoint_state = MCA_BTL_TCP_SHUTDOWN;    OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_send_lock);    OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_recv_lock);}/* *  Setup endpoint state to reflect that connection has been established, *  and start any pending sends. */static void mca_btl_tcp_endpoint_connected(mca_btl_base_endpoint_t* btl_endpoint){    /* setup socket options */    btl_endpoint->endpoint_state = MCA_BTL_TCP_CONNECTED;    btl_endpoint->endpoint_retries = 0;    if(opal_list_get_size(&btl_endpoint->endpoint_frags) > 0) {        if(NULL == btl_endpoint->endpoint_send_frag)            btl_endpoint->endpoint_send_frag = (mca_btl_tcp_frag_t*)                opal_list_remove_first(&btl_endpoint->endpoint_frags);        opal_event_add(&btl_endpoint->endpoint_send_event, 0);    }}/* * A blocking recv on a non-blocking socket. Used to receive the small amount of connection * information that identifies the endpoints endpoint. */static int mca_btl_tcp_endpoint_recv_blocking(mca_btl_base_endpoint_t* btl_endpoint, void* data, size_t size){    unsigned char* ptr = (unsigned char*)data;    size_t cnt = 0;    while(cnt < size) {        int retval = recv(btl_endpoint->endpoint_sd, (char *)ptr+cnt, size-cnt, 0);        /* remote closed connection */        if(retval == 0) {            mca_btl_tcp_endpoint_close(btl_endpoint);            return -1;        }        /* socket is non-blocking so handle errors */        if(retval < 0) {            if(opal_socket_errno != EINTR && opal_socket_errno != EAGAIN && opal_socket_errno != EWOULDBLOCK) {                BTL_ERROR(("recv() failed with errno=%d",opal_socket_errno));                mca_btl_tcp_endpoint_close(btl_endpoint);                return -1;            }            continue;        }        cnt += retval;    }    return cnt;}/* *  Receive the endpoints globally unique process identification from a newly *  connected socket and verify the expected response. If so, move the *  socket to a connected state. */static int mca_btl_tcp_endpoint_recv_connect_ack(mca_btl_base_endpoint_t* btl_endpoint){    orte_process_name_t guid;    mca_btl_tcp_proc_t* btl_proc = btl_endpoint->endpoint_proc;    if((mca_btl_tcp_endpoint_recv_blocking(btl_endpoint, &guid, sizeof(orte_process_name_t))) != sizeof(orte_process_name_t)) {        return OMPI_ERR_UNREACH;    }    ORTE_PROCESS_NAME_NTOH(guid);    /* compare this to the expected values */    if(memcmp(&btl_proc->proc_name, &guid, sizeof(orte_process_name_t)) != 0) {        BTL_ERROR(("received unexpected process identifier [%lu,%lu,%lu]",             ORTE_NAME_ARGS(&guid)));        mca_btl_tcp_endpoint_close(btl_endpoint);        return OMPI_ERR_UNREACH;    }    /* connected */    mca_btl_tcp_endpoint_connected(btl_endpoint);#if OMPI_ENABLE_DEBUG && WANT_PEER_DUMP    mca_btl_tcp_endpoint_dump(btl_endpoint, "connected");#endif    return OMPI_SUCCESS;}void mca_btl_tcp_set_socket_options(int sd){    int optval;#if defined(TCP_NODELAY)    optval = 1;    if(setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval)) < 0) {        BTL_ERROR(("setsockopt(TCP_NODELAY) failed with errno=%d", opal_socket_errno));    }#endif#if defined(SO_SNDBUF)    if(mca_btl_tcp_component.tcp_sndbuf > 0 &&       setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (char *)&mca_btl_tcp_component.tcp_sndbuf, sizeof(int)) < 0) {        BTL_ERROR(("setsockopt(SO_SNDBUF) failed with errno %d", opal_socket_errno));    }#endif#if defined(SO_RCVBUF)    if(mca_btl_tcp_component.tcp_rcvbuf > 0 &&       setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (char *)&mca_btl_tcp_component.tcp_rcvbuf, sizeof(int)) < 0) {        BTL_ERROR(("setsockopt(SO_RCVBUF) failed with errno %d", opal_socket_errno));    }#endif}/* *  Start a connection to the endpoint. This will likely not complete, *  as the socket is set to non-blocking, so register for event *  notification of connect completion. On connection we send *  our globally unique process identifier to the endpoint and wait for *  the endpoints response. */static int mca_btl_tcp_endpoint_start_connect(mca_btl_base_endpoint_t* btl_endpoint){    int rc,flags;    struct sockaddr_in endpoint_addr;    btl_endpoint->endpoint_sd = socket(AF_INET, SOCK_STREAM, 0);    if (btl_endpoint->endpoint_sd < 0) {        btl_endpoint->endpoint_retries++;        return OMPI_ERR_UNREACH;    }    /* setup socket buffer sizes */    mca_btl_tcp_set_socket_options(btl_endpoint->endpoint_sd);    /* setup event callbacks */    mca_btl_tcp_endpoint_event_init(btl_endpoint, btl_endpoint->endpoint_sd);    /* setup the socket as non-blocking */    if((flags = fcntl(btl_endpoint->endpoint_sd, F_GETFL, 0)) < 0) {        BTL_ERROR(("fcntl(F_GETFL) failed with errno=%d", opal_socket_errno));    } else {        flags |= O_NONBLOCK;        if(fcntl(btl_endpoint->endpoint_sd, F_SETFL, flags) < 0)            BTL_ERROR(("fcntl(F_SETFL) failed with errno=%d", opal_socket_errno));    }    /* start the connect - will likely fail with EINPROGRESS */    endpoint_addr.sin_family = AF_INET;    endpoint_addr.sin_addr = btl_endpoint->endpoint_addr->addr_inet;    endpoint_addr.sin_port = btl_endpoint->endpoint_addr->addr_port;    if(connect(btl_endpoint->endpoint_sd, (struct sockaddr*)&endpoint_addr, sizeof(endpoint_addr)) < 0) {        /* non-blocking so wait for completion */        if(opal_socket_errno == EINPROGRESS || opal_socket_errno == EWOULDBLOCK) {            btl_endpoint->endpoint_state = MCA_BTL_TCP_CONNECTING;            opal_event_add(&btl_endpoint->endpoint_send_event, 0);            return OMPI_SUCCESS;        }        mca_btl_tcp_endpoint_close(btl_endpoint);        btl_endpoint->endpoint_retries++;        return OMPI_ERR_UNREACH;    }    /* send our globally unique process identifier to the endpoint */    if((rc = mca_btl_tcp_endpoint_send_connect_ack(btl_endpoint)) == OMPI_SUCCESS) {        btl_endpoint->endpoint_state = MCA_BTL_TCP_CONNECT_ACK;        opal_event_add(&btl_endpoint->endpoint_recv_event, 0);    } else {        mca_btl_tcp_endpoint_close(btl_endpoint);    }    return rc;}/* * Check the status of the connection. If the connection failed, will retry * later. Otherwise, send this processes identifier to the endpoint on the  * newly connected socket. */static void mca_btl_tcp_endpoint_complete_connect(mca_btl_base_endpoint_t* btl_endpoint){    int so_error = 0;    opal_socklen_t so_length = sizeof(so_error);    /* unregister from receiving event notifications */    opal_event_del(&btl_endpoint->endpoint_send_event);    /* check connect completion status */    if(getsockopt(btl_endpoint->endpoint_sd, SOL_SOCKET, SO_ERROR, (char *)&so_error, &so_length) < 0) {        BTL_ERROR(("getsockopt() failed with errno=%d", opal_socket_errno));        mca_btl_tcp_endpoint_close(btl_endpoint);        return;    }    if(so_error == EINPROGRESS || so_error == EWOULDBLOCK) {        opal_event_add(&btl_endpoint->endpoint_send_event, 0);        return;    }    if(so_error != 0) {        BTL_ERROR(("connect() failed with errno=%d", so_error));        mca_btl_tcp_endpoint_close(btl_endpoint);        return;    }    if(mca_btl_tcp_endpoint_send_connect_ack(btl_endpoint) == OMPI_SUCCESS) {        btl_endpoint->endpoint_state = MCA_BTL_TCP_CONNECT_ACK;        opal_event_add(&btl_endpoint->endpoint_recv_event, 0);    } else {        mca_btl_tcp_endpoint_close(btl_endpoint);    }}/* * A file descriptor is available/ready for recv. Check the state  * of the socket and take the appropriate action. */static void mca_btl_tcp_endpoint_recv_handler(int sd, short flags, void* user){    mca_btl_base_endpoint_t* btl_endpoint = (mca_btl_base_endpoint_t *)user;    OPAL_THREAD_LOCK(&btl_endpoint->endpoint_recv_lock);    switch(btl_endpoint->endpoint_state) {    case MCA_BTL_TCP_CONNECT_ACK:        {            mca_btl_tcp_endpoint_recv_connect_ack(btl_endpoint);            OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_recv_lock);            break;        }    case MCA_BTL_TCP_CONNECTED:        {            mca_btl_tcp_frag_t* frag;            frag = btl_endpoint->endpoint_recv_frag;            if(NULL == frag) {                int rc;                if(mca_btl_tcp_module.super.btl_max_send_size >                    mca_btl_tcp_module.super.btl_eager_limit) {                     MCA_BTL_TCP_FRAG_ALLOC_MAX(frag, rc);                } else {                     MCA_BTL_TCP_FRAG_ALLOC_EAGER(frag, rc);                }                                if(NULL == frag) {                    OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_recv_lock);                    return;                }                MCA_BTL_TCP_FRAG_INIT_DST(frag, btl_endpoint);            }#if MCA_BTL_TCP_ENDPOINT_CACHE            assert( 0 == btl_endpoint->endpoint_cache_length );        data_still_pending_on_endpoint:#endif  /* MCA_BTL_TCP_ENDPOINT_CACHE */            /* check for completion of non-blocking recv on the current fragment */            if(mca_btl_tcp_frag_recv(frag, sd) == false) {                btl_endpoint->endpoint_recv_frag = frag;            } else {                btl_endpoint->endpoint_recv_frag = NULL;		if( MCA_BTL_TCP_HDR_TYPE_SEND == frag->hdr.type ) {		  mca_btl_base_recv_reg_t* reg = frag->btl->tcp_reg + frag->hdr.base.tag;		  reg->cbfunc(&frag->btl->super, frag->hdr.base.tag, &frag->base, reg->cbdata);                }#if MCA_BTL_TCP_ENDPOINT_CACHE                if( 0 != btl_endpoint->endpoint_cache_length ) {		    /* If the cache still contain some data we can reuse the same fragment		     * until we flush it completly.		     */                    MCA_BTL_TCP_FRAG_INIT_DST(frag, btl_endpoint);                    goto data_still_pending_on_endpoint;                }#endif  /* MCA_BTL_TCP_ENDPOINT_CACHE */                MCA_BTL_TCP_FRAG_RETURN(frag);            }            OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_recv_lock);#if MCA_BTL_TCP_ENDPOINT_CACHE            assert( 0 == btl_endpoint->endpoint_cache_length );#endif  /* MCA_BTL_TCP_ENDPOINT_CACHE */            break;        }    case MCA_BTL_TCP_SHUTDOWN:        OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_recv_lock);        break;    default:        OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_recv_lock);        BTL_ERROR(("invalid socket state(%d)", btl_endpoint->endpoint_state));        mca_btl_tcp_endpoint_close(btl_endpoint);        break;    }}/* * A file descriptor is available/ready for send. Check the state * of the socket and take the appropriate action. */static void mca_btl_tcp_endpoint_send_handler(int sd, short flags, void* user){    mca_btl_tcp_endpoint_t* btl_endpoint = (mca_btl_tcp_endpoint_t *)user;    OPAL_THREAD_LOCK(&btl_endpoint->endpoint_send_lock);    switch(btl_endpoint->endpoint_state) {    case MCA_BTL_TCP_CONNECTING:        mca_btl_tcp_endpoint_complete_connect(btl_endpoint);        break;    case MCA_BTL_TCP_CONNECTED:        {        /* complete the current send */        do {            mca_btl_tcp_frag_t* frag = btl_endpoint->endpoint_send_frag;            if(mca_btl_tcp_frag_send(frag, btl_endpoint->endpoint_sd) == false) {                break;            }            /* progress any pending sends */            btl_endpoint->endpoint_send_frag = (mca_btl_tcp_frag_t*)                opal_list_remove_first(&btl_endpoint->endpoint_frags);            /* if required - update request status and release fragment */            OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_send_lock);            frag->base.des_cbfunc(&frag->btl->super, frag->endpoint, &frag->base, frag->rc);            OPAL_THREAD_LOCK(&btl_endpoint->endpoint_send_lock);        } while (NULL != btl_endpoint->endpoint_send_frag);        /* if nothing else to do unregister for send event notifications */        if(NULL == btl_endpoint->endpoint_send_frag) {            opal_event_del(&btl_endpoint->endpoint_send_event);        }        break;        }    default:        BTL_ERROR(("invalid connection state (%d)",            btl_endpoint->endpoint_state));        opal_event_del(&btl_endpoint->endpoint_send_event);        break;    }    OPAL_THREAD_UNLOCK(&btl_endpoint->endpoint_send_lock);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?