static II_BOOL sm_execute ( IIAPI_ACTION action, IIAPI_HNDL *ev_hndl, IIAPI_HNDL *sm_hndl, II_PTR parmBlock ) { IIAPI_TRANHNDL *tranHndl = (IIAPI_TRANHNDL *)sm_hndl; IIAPI_MSG_BUFF *msgBuff; IIAPI_STATUS status; II_BOOL success = TRUE; char queryText[ 64 ]; switch( action ) { case SQL_TA_REMC : /* ** Remember callback. */ tranHndl->th_callback = TRUE; tranHndl->th_parm = (IIAPI_GENPARM *)parmBlock; break; case SQL_TA_RECV : { /* ** Issue receive message request. */ IIAPI_MSG_BUFF *msgBuff = IIapi_allocMsgBuffer( sm_hndl ); if ( ! msgBuff ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIapi_rcvNormalGCA( sm_hndl, msgBuff, (II_LONG)(-1) ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_SCOM : /* ** Format and send GCA_COMMIT message. */ if ( ! (msgBuff = IIapi_allocMsgBuffer( sm_hndl )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } msgBuff->msgType = GCA_COMMIT; msgBuff->flags = IIAPI_MSG_EOD; status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SRB : /* ** Format and send GCA_ROLLBACK message. */ if ( ! (msgBuff = IIapi_allocMsgBuffer( sm_hndl )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } msgBuff->msgType = GCA_ROLLBACK; msgBuff->flags = IIAPI_MSG_EOD; status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SSP : { /* ** Create savepoint handle. Format and ** send GCA_QUERY message 'savepoint <sp>'. */ IIAPI_SAVEPTHNDL *savePtHndl; IIAPI_SAVEPTPARM *savePtParm = (IIAPI_SAVEPTPARM *)parmBlock; if ( ! IIapi_createSavePtHndl( savePtParm ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } savePtHndl = savePtParm->sp_savePointHandle; STprintf( queryText, "savepoint %s\n", savePtHndl->sp_savePtName ); if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, queryText )) ) { IIapi_deleteSavePtHndl( savePtHndl ); savePtParm->sp_savePointHandle = NULL; status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) { IIapi_deleteSavePtHndl( savePtHndl ); savePtParm->sp_savePointHandle = NULL; success = FALSE; } break; } case SQL_TA_SRBS : { /* ** Format and send GCA_QUERY message 'rollback to <savepoint>'. */ IIAPI_ROLLBACKPARM *rollParm = (IIAPI_ROLLBACKPARM *)parmBlock; IIAPI_SAVEPTHNDL *savePtHndl = rollParm->rb_savePointHandle; STprintf(queryText, "rollback to %s\n", savePtHndl->sp_savePtName); if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, queryText )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_SAON : /* ** Format and send GCA_QUERY message 'set autocommit on'. */ if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, "set autocommit on" )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SAOF : /* ** Format and send GCA_QUERY message 'set autocommit off'. */ if ( ! (msgBuff = IIapi_createMsgQuery( sm_hndl, "set autocommit off" )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SSEC : /* ** Format and send GCA_SECURE message. */ if ( ! ( msgBuff = IIapi_createMsgSecure( tranHndl ) ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; case SQL_TA_SXAS : { /* ** Send XA Start message. */ IIAPI_XASTARTPARM *startParm = (IIAPI_XASTARTPARM *)parmBlock; if ( ! (msgBuff = IIapi_createMsgXA( sm_hndl, GCA_XA_START, &startParm->xs_tranID.ti_value.xaXID, startParm->xs_flags )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_SXAE : { /* ** Send XA End message. */ IIAPI_XAENDPARM *endParm = (IIAPI_XAENDPARM *)parmBlock; if ( ! (msgBuff = IIapi_createMsgXA( sm_hndl, GCA_XA_END, &endParm->xe_tranID.ti_value.xaXID, endParm->xe_flags )) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } status = IIapi_sndGCA( sm_hndl, msgBuff, NULL ); if ( status != IIAPI_ST_SUCCESS ) success = FALSE; break; } case SQL_TA_PEND : /* ** Return transaction aborted to all pending operations. */ { IIAPI_STMTHNDL *stmtHndl; for( stmtHndl = (IIAPI_STMTHNDL *)tranHndl-> th_stmtHndlList.q_next; stmtHndl != (IIAPI_STMTHNDL *)&tranHndl->th_stmtHndlList; stmtHndl = (IIAPI_STMTHNDL *)stmtHndl-> sh_header.hd_id.hi_queue.q_next ) IIapi_abortStmtHndl( stmtHndl, E_AP0002_TRANSACTION_ABORTED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ); } break; case SQL_TA_DELH : /* ** Mark handle for deletion. */ QUremove( (QUEUE *)tranHndl ); sm_hndl->hd_delete = TRUE; /* ** If this was a distributed transaction, ** the associated distributed transaction ** name should be releasable during the ** callback. Since the transaction handle ** has not actually been deleted, it is ** still associated with the distributed ** transaction name. Normally, cases such ** as this are serialized by the dispatch ** operations queue, but IIapi_releaseXID() ** is not a dispatched request. So we need ** to drop the association prior to making ** the callback. */ if ( tranHndl->th_tranName ) { QUremove( &tranHndl->th_tranNameQue ); tranHndl->th_tranName = NULL; } break; case SQL_TA_DELX : /* ** Free associated transaction name handle. */ if ( tranHndl->th_tranName ) /* Should never be NULL */ { QUremove( &tranHndl->th_tranNameQue ); IIapi_deleteTranName( tranHndl->th_tranName ); tranHndl->th_tranName = NULL; } /* ** Mark handle for deletion. */ QUremove( (QUEUE *)tranHndl ); sm_hndl->hd_delete = TRUE; break; case SQL_TA_ERAB : /* ** Transaction Aborted. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s: Transaction aborted\n", sql_tran_sm.sm_id ); if ( ! IIapi_localError( sm_hndl, E_AP0002_TRANSACTION_ABORTED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; } break; case SQL_TA_ERCF : /* ** Commit failed. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s: transaction commit failed\n", sql_tran_sm.sm_id ); if ( ! IIapi_localError( sm_hndl, E_AP000B_COMMIT_FAILED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; } break; case SQL_TA_ERPC : /* ** Prepare-to-commit failed. */ IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s: transaction prepare failed\n", sql_tran_sm.sm_id ); if ( ! IIapi_localError( sm_hndl, E_AP000C_2PC_REFUSED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; } break; case SQL_TA_RRSP : { /* ** Read response message. */ IIAPI_MSG_BUFF *msgBuff = (IIAPI_MSG_BUFF *)parmBlock; GCA_RE_DATA respData; if ( (status = IIapi_readMsgResponse( msgBuff, &respData, TRUE )) != IIAPI_ST_SUCCESS ) { success = FALSE; break; } /* ** Check for XA error */ if ( respData.gca_rqstatus & GCA_XA_ERROR_MASK && respData.gca_errd5 && ! IIapi_xaError( sm_hndl, respData.gca_errd5 ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } break; } case SQL_TA_RXAR : { /* ** Read XA response message. */ IIAPI_MSG_BUFF *msgBuff = (IIAPI_MSG_BUFF *)parmBlock; GCA_RE_DATA respData; if ( (status = IIapi_readMsgResponse( msgBuff, &respData, TRUE )) != IIAPI_ST_SUCCESS ) { success = FALSE; break; } /* ** If no XA error is returned, generate generic XA error. */ if ( ! (respData.gca_rqstatus & GCA_XA_ERROR_MASK) || ! respData.gca_errd5 ) respData.gca_errd5 = IIAPI_XAER_RMERR; if ( ! IIapi_xaError( sm_hndl, respData.gca_errd5 ) ) { status = IIAPI_ST_OUT_OF_MEMORY; success = FALSE; break; } break; } case SQL_TA_CBOK : /* ** Callback with success. Note that ** this will pick up the most severe ** status from the errors associated ** with the event handle. */ if ( tranHndl->th_callback ) { IIapi_appCallback(tranHndl->th_parm, sm_hndl, IIAPI_ST_SUCCESS); tranHndl->th_callback = FALSE; } break; case SQL_TA_CBFL : /* ** Callback with failure. */ if ( tranHndl->th_callback ) { IIapi_appCallback(tranHndl->th_parm, sm_hndl, IIAPI_ST_FAILURE); tranHndl->th_callback = FALSE; } break; case SQL_TA_CBIF : /* ** API function called in wrong state. */ if ( ! IIapi_localError( sm_hndl, E_AP0006_INVALID_SEQUENCE, II_SS5000R_RUN_TIME_LOGICAL_ERROR, IIAPI_ST_FAILURE ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; /* ** This may not have been a transaction ** related function, and we may have a ** callback saved on the transaction ** handle, so we carefully make the ** callback to the caller making sure ** not to disturb the transaction handle. */ IIapi_appCallback( (IIAPI_GENPARM *)parmBlock, sm_hndl, status ); break; case SQL_TA_CBAB : /* ** Callback with transaction abort. */ if ( tranHndl->th_callback ) { if ( ! IIapi_localError( sm_hndl, E_AP0002_TRANSACTION_ABORTED, II_SS40001_SERIALIZATION_FAIL, IIAPI_ST_FAILURE ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } break; case SQL_TA_CBABX : /* ** Callback with XA transaction abort. */ if ( tranHndl->th_callback ) { if ( ! IIapi_xaError( sm_hndl, IIAPI_XA_RBROLLBACK ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } break; case SQL_TA_RCVE : /* ** Receive error. ** ** We have received an invalid message. ** Since the connection state machine ** may ignore this particular message ** type, convert to a type which will ** ensure the proper handling in all ** state machines. */ IIapi_liDispatch( IIAPI_EV_UNEXPECTED_RCVD, sm_hndl, NULL, NULL ); break; case SQL_TA_HALT : /* ** Halt state machine execution. */ return( FALSE ); } /* ** If we couldn't complete the action, callback with failure. */ if ( ! success && tranHndl->th_callback ) { IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } return( success ); }
static II_BOOL sm_execute ( IIAPI_ACTION action, IIAPI_HNDL *ev_hndl, IIAPI_HNDL *sm_hndl, II_PTR parmBlock ) { IIAPI_TRANHNDL *tranHndl = (IIAPI_TRANHNDL *)sm_hndl; IIAPI_SAVEPTHNDL *savePtHndl; IIAPI_SAVEPTPARM *savePtParm; IIAPI_STATUS status = OK; II_BOOL success = TRUE; char queryText[ 64 ]; switch( action ) { case NS_TA_REMC : /* ** Remember callback. */ tranHndl->th_callback = TRUE; tranHndl->th_parm = (IIAPI_GENPARM *)parmBlock; break; case NS_TA_DELH : /* ** Mark handle for deletion. */ QUremove( (QUEUE *)tranHndl ); sm_hndl->hd_delete = TRUE; break; case NS_TA_CBOK : /* ** Callback with success. Note that ** this will pick up the most severe ** status from the errors associated ** with the event handle. */ if ( tranHndl->th_callback ) { IIapi_appCallback(tranHndl->th_parm, sm_hndl, IIAPI_ST_SUCCESS); tranHndl->th_callback = FALSE; } break; case NS_TA_CBIF : /* ** API function called in wrong state. */ if ( ! IIapi_localError( sm_hndl, E_AP0006_INVALID_SEQUENCE, II_SS5000R_RUN_TIME_LOGICAL_ERROR, IIAPI_ST_FAILURE ) ) status = IIAPI_ST_OUT_OF_MEMORY; else status = IIAPI_ST_FAILURE; /* ** This may not have been a transaction ** related function, and we may have a ** callback saved on the transaction ** handle, so we carefully make the ** callback to the caller making sure ** not to disturb the transaction handle. */ IIapi_appCallback( (IIAPI_GENPARM *)parmBlock, sm_hndl, status ); /* ** We must return the failure here rather ** than following the normal exit route ** to ensure that the transaction handle ** callback does not get made. */ return( FALSE ); case NS_TA_RCVE : /* ** Receive error. ** ** We have received an invalid message. ** Since the connection state machine ** may ignore this particular message ** type, convert to a type which will ** ensure the proper handling in all ** state machines. */ IIapi_liDispatch( IIAPI_EV_UNEXPECTED_RCVD, sm_hndl, NULL, NULL ); return( FALSE ); } /* ** If we couldn't complete the action, callback with failure. */ if ( ! success && tranHndl->th_callback ) { IIapi_appCallback( tranHndl->th_parm, sm_hndl, status ); tranHndl->th_callback = FALSE; } return( success ); }