Exemplo n.º 1
0
int ax_reg(int rmid, XID *xid, long flags)
{
    enum Exception { CLIENT_NOT_INITIALIZED
                     , COLL_GET_CS_ERROR
                     , OUT_OF_RANGE
                     , NOT_DYNAMIC
                     , INVALID_TX_STATE
                     , MSG_SERIALIZE_ERROR
                     , MSG_SEND_ERROR
                     , NONE } excp;
    int ret_cod = TMER_TMERR;
    int xa_ret_cod = TM_OK;

    LIXA_TRACE_INIT;
    LIXA_TRACE(("ax_reg: rmid=%d, xid=%p, flags=0x%lx\n", rmid, xid, flags));
    TRY {
        client_status_t *cs;
        struct client_status_rsrmgr_s *csr;
        struct lixa_msg_s msg;
        size_t buffer_size = 0;
        int fd, txstate, next_xa_td_state = XA_STATE_D1;
        char buffer[LIXA_MSG_XML_BUFFER_SIZE];
        struct act_rsrmgr_config_s *act_rsrmgr;
        lixa_ser_xid_t ser_xid = "";

        /* retrieve a reference to the thread status */
        ret_cod = client_status_coll_get_cs(&global_csc, &cs);
        switch (ret_cod) {
            case LIXA_RC_OK: /* nothing to do */
                break;
            case LIXA_RC_OBJ_NOT_FOUND:
                LIXA_TRACE(("ax_reg: status not found\n"));
                THROW(CLIENT_NOT_INITIALIZED);
                break;
            default:
                THROW(COLL_GET_CS_ERROR);
        }
        
        /* check the rmid value is not out of range */
        if (0 > rmid || global_ccc.actconf.rsrmgrs->len <= rmid) {
            LIXA_TRACE(("ax_unreg: rmid out of range\n"));
            THROW(OUT_OF_RANGE);
        }
        
        /* check the resource manager declared dynamic registration */
        if (TM_OK == xa_ret_cod) {
            act_rsrmgr = &g_array_index(
                global_ccc.actconf.rsrmgrs, struct act_rsrmgr_config_s, rmid);
            if (!(TMREGISTER & act_rsrmgr->xa_switch->flags)) {
                LIXA_TRACE(("ax_reg: resource manager %d ('%s') did not set "
                            "TMREGISTER flag (flags=0x%lx)\n", rmid,
                            act_rsrmgr->xa_switch->name,
                            act_rsrmgr->xa_switch->flags));
                xa_ret_cod = TMER_TMERR;
            }
        }
        
        /* check the status of the transaction manager */
        txstate = client_status_get_txstate(cs);
        if (TM_OK == xa_ret_cod)
            switch (txstate) {
                case TX_STATE_S0:
                    LIXA_TRACE(("ax_reg: the transaction has not yet opened "
                                "the resource managers (TX state S%d)\n",
                                txstate));
                    xa_ret_cod = TMER_PROTO;
                    break;
                case TX_STATE_S1:
                case TX_STATE_S2:
                    LIXA_TRACE(("ax_reg: the application program has not yet "
                                "started a transaction (TX states S%d); "
                                "null XID will be returned\n", txstate));
                    xid->formatID = -1;
                    next_xa_td_state = XA_STATE_D3;
                    break;
                case TX_STATE_S3:
                case TX_STATE_S4:
                    lixa_xid_serialize(client_status_get_xid(cs), ser_xid);
#ifdef _TRACE
                    LIXA_TRACE(("ax_reg: the application program has "
                                "started a transaction (TX states S%d); "
                                "this XID '%s' will be returned\n",
                                txstate,
                                NULL == ser_xid ? "" : ser_xid));
#endif
                    memcpy(xid, client_status_get_xid(cs), sizeof(XID));
                    break;
                default:
                    LIXA_TRACE(("ax_reg: invalid TX state (%d)\n", txstate));
                    THROW(INVALID_TX_STATE);
            }
        
        /* check the status of the resource manager */
        csr = &g_array_index(cs->rmstatus, struct client_status_rsrmgr_s,
                             rmid);
        if ((TM_OK == xa_ret_cod) && !csr->common.dynamic) {
            LIXA_TRACE(("ax_reg: resource manager # %d is not using "
                        "dynamic registration\n", rmid));
            xa_ret_cod = TMER_INVAL;
        }

        if ((TM_OK == xa_ret_cod) && (XA_STATE_R1 != csr->common.xa_r_state)) {
            LIXA_TRACE(("ax_reg: invalid XA r_state (%d)\n",
                        csr->common.xa_r_state));
            xa_ret_cod = TMER_PROTO;
        }

        if ((TM_OK == xa_ret_cod) &&
            (XA_STATE_D0 != csr->common.xa_td_state)) {
            LIXA_TRACE(("ax_reg: invalid XA td_state (%d)\n",
                        csr->common.xa_td_state));
            xa_ret_cod = TMER_PROTO;
        }

        /* build the message */
        msg.header.level = LIXA_MSG_LEVEL;
        msg.header.pvs.verb = LIXA_MSG_VERB_REG;
        msg.header.pvs.step = LIXA_MSG_STEP_INCR;
        
        msg.body.reg_8.ax_reg_exec.rmid = rmid;
        msg.body.reg_8.ax_reg_exec.flags = flags;
        msg.body.reg_8.ax_reg_exec.rc = ret_cod;
        msg.body.reg_8.ax_reg_exec.td_state = next_xa_td_state;
        if (XA_STATE_D1 == next_xa_td_state)
            msg.body.reg_8.ax_reg_exec.s_state = XA_STATE_S1;
        else
            msg.body.reg_8.ax_reg_exec.s_state = csr->common.xa_s_state;
        
        if (LIXA_RC_OK != (ret_cod = lixa_msg_serialize(
                               &msg, buffer, sizeof(buffer), &buffer_size)))
            THROW(MSG_SERIALIZE_ERROR);
        
        /* retrieve the socket */
        fd = client_status_get_sockfd(cs);
        LIXA_TRACE(("ax_reg: sending " SIZE_T_FORMAT
                    " bytes to the server for step 8\n", buffer_size));
        if (LIXA_RC_OK != (ret_cod = lixa_msg_send(fd, buffer, buffer_size))) {
            if (LIXA_RC_CONNECTION_CLOSED == ret_cod)
                client_status_set_sockfd(cs, LIXA_NULL_FD);
            THROW(MSG_SEND_ERROR);
        }
        
        LIXA_CRASH(LIXA_CRASH_POINT_LIXA_AX_REG_1,
                   client_status_get_crash_count(cs));
        
        /* new resource manager state */
        csr->common.xa_td_state = next_xa_td_state;
        if (XA_STATE_D1 == next_xa_td_state)
            csr->common.xa_s_state = XA_STATE_S1;
        
        THROW(NONE);
    } CATCH {
Exemplo n.º 2
0
int client_connect(client_status_coll_t *csc,
                   client_config_coll_t *ccc)
{
    enum Exception { GET_STTSRV_ERROR
                     , SOCKET_ERROR
                     , CONNECT_ERROR
                     , SETSOCKOPT_ERROR
                     , CLIENT_STATUS_COLL_GET_CS_ERROR
                     , NONE } excp;
    int ret_cod = LIXA_RC_INTERNAL_ERROR;

    int out_socket;
    struct sttsrv_config_s *tc;
    
    LIXA_TRACE(("client_connect\n"));
    TRY {
        client_status_t *cs;
        int sock_opt = 1;

        /* search connection parameters */
        if (NULL == (tc = client_config_get_sttsrv(ccc)))
            THROW(GET_STTSRV_ERROR);

        /* create new socket */
        if (LIXA_NULL_FD == (out_socket = socket(tc->domain, SOCK_STREAM, 0)))
            THROW(SOCKET_ERROR);

        LIXA_TRACE(("client_connect: connecting socket %d to server '%s' port "
                    IN_PORT_T_FORMAT "\n", out_socket, tc->address, tc->port));
        if (0 != connect(out_socket, (struct sockaddr *)&ccc->serv_addr,
                         sizeof(struct sockaddr_in))) {
            syslog(LOG_ERR, LIXA_SYSLOG_LXC002E, tc->address, tc->port);
            THROW(CONNECT_ERROR);
        }

        /* disable Nagle's algorithm to reduce latency */
        if (0 != setsockopt(out_socket, IPPROTO_TCP, TCP_NODELAY,
                            (void *)(&sock_opt), sizeof(sock_opt)))
            THROW(SETSOCKOPT_ERROR);
        
        if (LIXA_RC_OK != (ret_cod = client_status_coll_get_cs(csc, &cs)))
            THROW(CLIENT_STATUS_COLL_GET_CS_ERROR);
        LIXA_TRACE(("client_connect: cs = %p\n", cs));
        LIXA_CRASH(LIXA_CRASH_POINT_CLIENT_CONNECT_1,
                   client_status_get_crash_count(cs));
        
        client_status_set_sockfd(cs, out_socket);
        
        THROW(NONE);
    } CATCH {
        switch (excp) {
            case GET_STTSRV_ERROR:
                ret_cod = LIXA_RC_NULL_OBJECT;
                break;
            case SOCKET_ERROR:
                break;
            case CONNECT_ERROR:
                ret_cod = LIXA_RC_CONNECT_ERROR;
                break;
            case SETSOCKOPT_ERROR:
                ret_cod = LIXA_RC_SETSOCKOPT_ERROR;
                break;                
            case CLIENT_STATUS_COLL_GET_CS_ERROR:
                break;
            case NONE:
                ret_cod = LIXA_RC_OK;
                break;
            default:
                ret_cod = LIXA_RC_INTERNAL_ERROR;
        } /* switch (excp) */
    } /* TRY-CATCH */
    LIXA_TRACE(("client_connect/excp=%d/"
                "ret_cod=%d/errno=%d\n", excp, ret_cod, errno));
    return ret_cod;
}