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 {
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; }