Пример #1
0
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 );
}
Пример #2
0
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 );
}