Пример #1
0
/* PROGRAM: dsmTransaction - commit or rollback a transaction or savepoint.
 *
 * RETURNS: DSM_S_SUCCESS
 *          DSM_S_BADSAVE - invalid savepoint passed.
 *          DSM_S_TRANSACTION_ALREADY_STARTED - transaction already started.
 *          DSM_S_NO_TRANSACTION - a transaction operation request
 *                                 was issued prior to a start request.
 *          DSM_S_INVALID_TRANSACTION_CODE - invalid transaction code.
 *          DSM_S_FAILURE
 */
dsmStatus_t
dsmTransaction(
	dsmContext_t  *pcontext,   /* IN/OUT database context */
        dsmTxnSave_t  *pSavePoint, /* IN/OUT savepoint        */
        dsmTxnCode_t  txnCode)     /* IN function code       */
{
    int returnCode;
    int  forceAbort;
    dbcontext_t  *pdbcontext = pcontext->pdbcontext;
    usrctl_t     *pusr       = pcontext->pusrctl;

    pdbcontext->inservice++;

    if (pdbcontext->prlctl == (RLCTL *)NULL)
    {
        /* Logging disabled */
        if (pdbcontext->dbcode != PROCODET)
        {
            /* Not a temp-table database */
	    return DSM_S_SUCCESS;
	}
    }

    SETJMP_ERROREXIT(pcontext, returnCode) /* Ensure error exit address set */

    if ((returnCode = dsmThreadSafeEntry(pcontext)) != DSM_S_SUCCESS)
    {
        /* If the user is marked to die it was decided to allow the
         * transaction operation to completed for 4gl compatibility */
        if ( ( (returnCode == DSM_S_USER_TO_DIE) &&
               (pcontext->pdbcontext->accessEnv == DSM_4GL_ENGINE) ) == 0 )
        {   
            returnCode = dsmEntryProcessError(pcontext, returnCode,
                          (TEXT *)"dsmTransaction");
            goto done;
        }
    }

    returnCode = DSM_S_SUCCESS; /* assume success */

    if( txnCode == DSMTXN_START )
    {

        /* Check to make sure that we are not trying to start a 
           transaction on a task that already has a transaction */
        if (pusr->uc_task)
        {
            returnCode = DSM_S_TRANSACTION_ALREADY_STARTED;
            goto done;
        }

        /* Transaction begin starts an implicit savepoint of 1 */
        tmstrt(pcontext);
    }
    else if ( txnCode == DSMTXN_COMMIT )
    {
        /* Check to make sure a transaction start was issued prior */
        if (pusr->uc_task == 0)
        {
            returnCode = DSM_S_NO_TRANSACTION;
            goto done;
        }

        returnCode = tmend(pcontext, TMACC, NULL, 1 );
    }
    else if ( txnCode == DSMTXN_SAVE )
    {
        /* Make sure a transaction begin has been executed */
        if ( !pSavePoint || (*pSavePoint < (DSMTXN_SAVE_MINIMUM + 1)) )
        {
            returnCode = DSM_S_BADSAVE;
            goto done;
        }

        /* Mark the savepoint specified by the user */
        returnCode = tmMarkSavePoint(pcontext, pSavePoint);
    }
    else if ( txnCode == DSMTXN_ABORT || txnCode == DSMTXN_FORCE ||
              txnCode == DSMTXN_UNSAVE )
    {
        if( txnCode == DSMTXN_FORCE )
            forceAbort = 1;
        else
            forceAbort = 0;

        /* Check to make sure a transaction start was issued prior */
        if (pusr->uc_task == 0)
        {
            returnCode = DSM_S_NO_TRANSACTION;
            goto done;
        }

        /* Rollback the transaction and unmark the savepoint */
        if (pdbcontext->accessEnv == DSM_SQL_ENGINE)
        {
            if (!pSavePoint || (*pSavePoint > pcontext->pusrctl->uc_savePoint) )
            {
                returnCode = DSM_S_BADSAVE;
                goto done;
            }

            tmrej(pcontext, forceAbort, pSavePoint);
        }
        else
            tmrej(pcontext, forceAbort, (dsmTxnSave_t *)PNULL);

        if( !pSavePoint )  
        {
            /* savepoint pointer should not be null */
            returnCode = DSM_S_BADSAVE;
            goto done;
        }

        if( *pSavePoint == 0 )
            returnCode = tmend(pcontext, TMREJ, NULL, 1);

    }
    else if ( txnCode == DSMTXN_ABORTED )
    {
        /* Check to make sure a transaction start was issued prior */
        if (pusr->uc_task == 0)
        {
            returnCode = DSM_S_NO_TRANSACTION;
            goto done;
        }

        returnCode = tmend(pcontext, TMREJ, NULL, 1 );
    }
    else if ( txnCode == DSMTXN_PHASE1 )
    {
        /* Check to make sure a transaction start was issued prior */
        if (pusr->uc_task == 0)
        {
            returnCode = DSM_S_NO_TRANSACTION;
            goto done;
        }

        returnCode = tmend(pcontext, PHASE1, NULL, 1 );
    }
    else if (txnCode == DSMTXN_PHASE1Q2)
    {
        /* Check to make sure a transaction start was issued prior */
        if (pusr->uc_task == 0)
        {
            returnCode = DSM_S_NO_TRANSACTION;
            goto done;
        }

        returnCode = tmend(pcontext, PHASE1q2,NULL, 1);
    }
    else
    {
        /* Indicate that an invalid txnCode was passed to dsmTransaction */
        returnCode = DSM_S_INVALID_TRANSACTION_CODE;
    }
    
done:
    dsmThreadSafeExit(pcontext);

    pdbcontext->inservice--;
    return((dsmStatus_t) returnCode);

}  /* end dsmTransaction */
Пример #2
0
/* PROGRAM: dbxaEnd - End an association with a global transaction

   RETURNS:
   */
dsmStatus_t
dbxaEnd(dsmContext_t *pcontext, dbxaTransaction_t *pxaTran, LONG flags)
{
    dsmStatus_t returnCode = DSM_S_SUCCESS;
    usrctl_t    *pusr = pcontext->pusrctl;
    
    if(pxaTran->trid != pcontext->pusrctl->uc_task)
    {
        /* Maybe we're ending a suspended association */
        if(pcontext->pusrctl->uc_task == 0 &&
           pxaTran->numSuspended)
        {
            /* That must be what it is  */
            ;
        }
        else
        {
            returnCode = DSM_S_XAER_NOTA;
            goto done;
        }
    }
    if(pxaTran->flags & DSM_XA_PREPARED)
    {
        returnCode = DSM_S_XAER_PROTO;
        goto done;
    }
    
    switch (flags)
    {
        case DSM_TMSUCCESS:
            {
                MT_LOCK_TXT();
                pxaTran->referenceCount--;

                if(pusr->uc_task)
                    pusr->uc_task = 0;
                else
                    pxaTran->numSuspended--;
                
                pxaTran->lastRLblock = pusr->uc_lastBlock;
                pxaTran->lastRLoffset = pusr->uc_lastOffset;
                MT_UNLK_TXT();
                break;
            }
        case DSM_TMSUSPEND:
            {
                pusr->uc_task = 0;
                MT_LOCK_TXT();
                pxaTran->lastRLblock = pusr->uc_lastBlock;
                pxaTran->lastRLoffset = pusr->uc_lastOffset;                
                pxaTran->numSuspended++;
                MT_UNLK_TXT();
                break;
            }
        case DSM_TMFAIL:
            {
                MT_LOCK_TXT();
                pxaTran->referenceCount--;
                pxaTran->flags |= DSM_XA_ROLLBACK_ONLY;
                MT_UNLK_TXT();
                tmrej(pcontext,0,NULL);
                tmend(pcontext,TMREJ,NULL,1);

                break;
            }
        default:
            {
                returnCode = DSM_S_XAER_INVAL;
            }
    }
done:
    
    return returnCode;
}