static IIAPI_SM_OUT * sm_evaluate ( IIAPI_EVENT event, IIAPI_STATE state, IIAPI_HNDL *ev_hndl, IIAPI_HNDL *sm_hndl, II_PTR parmBlock, IIAPI_SM_OUT *smo_buff ) { IIAPI_TRANHNDL *tranHndl = (IIAPI_TRANHNDL *)sm_hndl; IIAPI_SM_OUT *smo = NULL; SM_TRANSITION *smt; IIAPI_TRACE( IIAPI_TR_VERBOSE ) ( "%s evaluate: evaluating event %s in state %s\n", sql_tran_sm.sm_id, IIAPI_PRINTEVENT( event ), IIAPI_PRINT_ID( state, SQL_TS_CNT, sql_ts_id ) ); /* ** Static evaluations depend solely on the current state and event. */ if ( (smt = smt_array[ event ][ state ]) ) { IIAPI_TRACE( IIAPI_TR_DETAIL ) ( "%s evaluate: static evaluation\n", sql_tran_sm.sm_id ); smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ smt->smt_action ], *smo ); smo->smo_next_state = smt->smt_next; } else /* Dynamic evaluations require additional predicates */ switch( event ) /* to determine the correct state transition. */ { /* ** Rollback requests may be for savepoints ** or the entire transaction. */ case IIAPI_EV_ROLLBACK_FUNC : if ( ((IIAPI_ROLLBACKPARM *)parmBlock)->rb_savePointHandle ) { /* ** Rollback to savepoint. */ switch( state ) { case SQL_TS_TRAN : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_12 ], *smo ); smo->smo_next_state = SQL_TS_RBSP; break; case SQL_TS_ABORT : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_21 ], *smo ); smo->smo_next_state = state; break; } } else { /* ** Rollback transaction. */ switch( state ) { case SQL_TS_IDLE : case SQL_TS_BEG : case SQL_TS_ABORT : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_10 ], *smo ); smo->smo_next_state = SQL_TS_IDLE; break; case SQL_TS_TRAN : case SQL_TS_PREP : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_13 ], *smo ); smo->smo_next_state = SQL_TS_ROLL; break; case SQL_TS_XA : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_13 ], *smo ); smo->smo_next_state = SQL_TS_XAEND; break; } } break; /* ** GCA_RESPONSE messages include the current DBMS ** transaction state, allowing detection of the ** start of a transaction and transaction aborts. ** In some cases, the query status is also of ** interest. */ case IIAPI_EV_RESPONSE_RCVD : { /* ** A fake GCA_RESPONSE message is generated for some cases ** of procedure execution. The GCA message buffer will be ** NULL in this case and it is assumed that the procedure ** executed successfully. ** ** The RESPONSE message is not consumed during evaluation. */ GCA_RE_DATA respData; if ( ! parmBlock || IIapi_readMsgResponse((IIAPI_MSG_BUFF *)parmBlock, &respData, FALSE) != IIAPI_ST_SUCCESS ) respData.gca_rqstatus = 0; if ( respData.gca_rqstatus & GCA_LOG_TERM_MASK ) { /* ** Transaction inactive (possibly aborted). */ switch( state ) { case SQL_TS_BEG : case SQL_TS_ABORT : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_0 ], *smo ); smo->smo_next_state = state; break; case SQL_TS_TRAN : case SQL_TS_XA : case SQL_TS_PREP : case SQL_TS_WSPR : case SQL_TS_WRSR : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_7 ], *smo ); smo->smo_next_state = SQL_TS_ABORT; break; } } else { /* ** Transaction active. */ switch( state ) { case SQL_TS_BEG : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_0 ], *smo ); smo->smo_next_state = SQL_TS_TRAN; break; case SQL_TS_TRAN : case SQL_TS_XA : case SQL_TS_PREP : case SQL_TS_ABORT : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_0 ], *smo ); smo->smo_next_state = state; break; case SQL_TS_WSPR : case SQL_TS_WRSR : smo = smo_buff; if ( respData.gca_rqstatus & GCA_FAIL_MASK ) STRUCT_ASSIGN_MACRO(sql_act_seq[SQL_TAS_9], *smo); else STRUCT_ASSIGN_MACRO(sql_act_seq[SQL_TAS_4], *smo); smo->smo_next_state = SQL_TS_TRAN; break; } } if ( respData.gca_rqstatus & GCA_FAIL_MASK ) { /* ** Request failed. */ switch( state ) { case SQL_TS_WONR : case SQL_TS_WOFR : smo = smo_buff; STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_18 ], *smo ); smo->smo_next_state = SQL_TS_IDLE; break; } } else { /* ** Request succedded. */ switch( state ) { case SQL_TS_WONR : smo = smo_buff; STRUCT_ASSIGN_MACRO(sql_act_seq[ SQL_TAS_4 ], *smo); smo->smo_next_state = SQL_TS_AUTO; break; case SQL_TS_WOFR : smo = smo_buff; STRUCT_ASSIGN_MACRO(sql_act_seq[ SQL_TAS_5 ], *smo); smo->smo_next_state = SQL_TS_IDLE; break; } } break; } /* ** GCA_REJECT messages should only occur in ** the connected state. They are processed ** by the connection SM. When significant, ** only handle when EOD. */ case IIAPI_EV_REJECT_RCVD : switch( state ) { case SQL_TS_CONN : { IIAPI_MSG_BUFF *msgBuff = (IIAPI_MSG_BUFF *)parmBlock; smo = smo_buff; if ( msgBuff->flags & IIAPI_MSG_EOD ) { STRUCT_ASSIGN_MACRO(sql_act_seq[ SQL_TAS_6 ], *smo); smo->smo_next_state = SQL_TS_IDLE; } else { smo->smo_action_cnt = 0; smo->smo_next_state = state; } break; } } break; /* ** GCA_RELEASE messages are mostly ignored. ** They are processed by the connection SM. ** When significant, only handle when EOD. */ case IIAPI_EV_RELEASE_RCVD : switch( state ) { case SQL_TS_IDLE : case SQL_TS_CONN : { IIAPI_MSG_BUFF *msgBuff = (IIAPI_MSG_BUFF *)parmBlock; smo = smo_buff; if ( msgBuff->flags & IIAPI_MSG_EOD ) { STRUCT_ASSIGN_MACRO(sql_act_seq[ SQL_TAS_6 ], *smo); smo->smo_next_state = SQL_TS_IDLE; } else { smo->smo_action_cnt = 0; smo->smo_next_state = state; } break; } default : /* ** Ignored in all other states. */ smo = smo_buff; smo->smo_next_state = state; smo->smo_action_cnt = 0; break; } break; /* ** The following events are ignored at the ** transaction level. They will be processed ** by the connection state machine. Since ** they are unconditionally ignored, it is ** easier to handle them here than maintaining ** static transitions for every state. */ case IIAPI_EV_ERROR_RCVD : case IIAPI_EV_EVENT_RCVD : case IIAPI_EV_NPINTERUPT_RCVD : case IIAPI_EV_TRACE_RCVD : case IIAPI_EV_PROMPT_RCVD : case IIAPI_EV_UNEXPECTED_RCVD : case IIAPI_EV_RESUME : case IIAPI_EV_RECV_ERROR : case IIAPI_EV_SEND_ERROR : smo = smo_buff; smo->smo_next_state = state; smo->smo_action_cnt = 0; break; } /* ** If a specific response was not generated above, ** produce a generalized error response. */ if ( ! smo ) { smo = smo_buff; if ( event <= IIAPI_EVENT_FUNC_MAX ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s Evaluate: API function called in wrong state\n", sql_tran_sm.sm_id ); STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_19 ], *smo ); smo->smo_next_state = state; } else if ( event <= IIAPI_EVENT_MSG_MAX ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s Evaluate: invalid message received\n", sql_tran_sm.sm_id ); STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_20 ], *smo ); smo->smo_next_state = state; } else { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s Evaluate: unexpected I/O completion\n", sql_tran_sm.sm_id ); STRUCT_ASSIGN_MACRO( sql_act_seq[ SQL_TAS_0 ], *smo ); smo->smo_next_state = state; } } /* ** If the input resulted in no state change ** and no actions to be executed, we can ** just ignore the event. */ if ( smo->smo_next_state == state && ! smo->smo_action_cnt ) { IIAPI_TRACE( IIAPI_TR_DETAIL ) ( "%s evaluate: nothing to do, transition ignored\n", sql_tran_sm.sm_id ); smo = NULL; } return( smo ); }
static IIAPI_SM_OUT * sm_evaluate ( IIAPI_EVENT event, IIAPI_STATE state, IIAPI_HNDL *ev_hndl, IIAPI_HNDL *sm_hndl, II_PTR parmBlock, IIAPI_SM_OUT *smo_buff ) { IIAPI_TRANHNDL *tranHndl = (IIAPI_TRANHNDL *)sm_hndl; IIAPI_SM_OUT *smo = NULL; SM_TRANSITION *smt; IIAPI_TRACE( IIAPI_TR_VERBOSE ) ( "%s evaluate: evaluating event %s in state %s\n", ns_tran_sm.sm_id, IIAPI_PRINTEVENT( event ), IIAPI_PRINT_ID( state, NS_TS_CNT, ns_ts_id ) ); /* ** Static evaluations depend solely on the current state and event. */ if ( (smt = smt_array[ event ][ state ]) ) { IIAPI_TRACE( IIAPI_TR_DETAIL ) ( "%s evaluate: static evaluation\n", ns_tran_sm.sm_id ); smo = smo_buff; STRUCT_ASSIGN_MACRO( ns_act_seq[ smt->smt_action ], *smo ); smo->smo_next_state = smt->smt_next; } /* ** If a specific response was not generated above, ** produce a generalized error response. */ if ( ! smo ) { smo = smo_buff; if ( event <= IIAPI_EVENT_FUNC_MAX ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s Evaluate: API function called in wrong state\n", ns_tran_sm.sm_id ); STRUCT_ASSIGN_MACRO( ns_act_seq[ NS_TAS_3 ], *smo ); smo->smo_next_state = state; } else if ( event <= IIAPI_EVENT_MSG_MAX ) { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s Evaluate: invalid message received\n", ns_tran_sm.sm_id ); STRUCT_ASSIGN_MACRO( ns_act_seq[ NS_TAS_4 ], *smo ); smo->smo_next_state = state; } else { IIAPI_TRACE( IIAPI_TR_ERROR ) ( "%s Evaluate: unexpected I/O completion\n", ns_tran_sm.sm_id ); STRUCT_ASSIGN_MACRO( ns_act_seq[ NS_TAS_0 ], *smo ); smo->smo_next_state = state; } } /* ** If the input resulted in no state change ** and no actions to be executed, we can ** just ignore the event. */ if ( smo->smo_next_state == state && ! smo->smo_action_cnt ) { IIAPI_TRACE( IIAPI_TR_DETAIL ) ( "%s evaluate: nothing to do, transition ignored\n", ns_tran_sm.sm_id ); smo = NULL; } return( smo ); }