Beispiel #1
0
int
mts_trx_commit (lock_trx_t * lt, int is_commit)
{
  tp_dtrx_t *dtrx = lt->lt_2pc._2pc_info;
  tp_data_t *tpd = lt->lt_client->cli_tp_data;

  if (tpd && (CONNECTION_ENLISTED == tpd->cli_tp_enlisted))
    {
      MTS_TRACE (("mts_trx_commit (connection level) %x\n", lt->lt_client));
      return 0;
    }
  if (dtrx->dtrx_info)
    {
      HRESULT hr;
      MTS_TRACE (("mts_trx_commit (transaction level) %x\n", lt));
      ITransaction *trx = ((mts_t *) dtrx->dtrx_info)->mts_trx;
      hr = is_commit ? trx->Commit (FALSE, 0, 0) : trx->Abort (0, 0, 0);
      trx->Release ();
      if (SUCCEEDED (hr))
	return LTE_OK;
      return LTE_DEADLOCK;

    }
  return 0;
}
int __cdecl wmain(int argc, WCHAR* argv[])
{
    HRESULT hr = E_FAIL;
    
    ITransaction* pITransaction = NULL;
    HANDLE hTransactionHandle = INVALID_HANDLE_VALUE;

    // Parse the command line to see if -abort switch is used or not.
    // If the abort switch is used the transaction will be aborted at the end,
    // otherwise it will be committed.
    ParseCommandLine(argc, argv);

    // Get a pointer to a new transaction
    hr = CreateTransaction(&pITransaction);
    if (FAILED(hr)) 
        goto cleanup;

    // Get a transaction handle to use with the transacted file operation
    hr = GetKernelTransactionHandle(pITransaction, &hTransactionHandle);
    if (FAILED(hr)) 
        goto cleanup;

    // Do a transacted file operation
    hr = TransactedFileOperation(hTransactionHandle);
    if (FAILED(hr)) 
        goto cleanup;


    //-------------------------------------------------------------------------
    // Here you can do other operations to various Resource Managers as part 
    // of this transaction using the same ITransaction.
    //-------------------------------------------------------------------------


    // Commit or abort the transaction depending on the g_fAbort boolean variable
    // which was set by using the -abort command line parameter
    hr = CommitOrAbortTransaction(pITransaction);
    if (FAILED(hr)) 
        goto cleanup;

cleanup:
    
    if(INVALID_HANDLE_VALUE != hTransactionHandle)
    {
        CloseHandle(hTransactionHandle);
        hTransactionHandle = INVALID_HANDLE_VALUE;
    }
    
    if(NULL != pITransaction)
    {
        pITransaction->Release();
        pITransaction = NULL;
    }

    return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
    // Starting up the resource manager
    // Note: In most of the cases, a "durable" resource manager lives in its own process
    // Here the resource manager is in the same process with the client for readability
    DTCResourceManager* resourceManager = NULL;
    try
    {
        resourceManager = new DTCResourceManager();    
    }
    catch( std::bad_alloc )
    {
        resourceManager = NULL;
    }
    if( NULL == resourceManager )
    {
        std::cout << "Failed to allocate memory. The program will exit." << std::endl;
        exit(1);
    }

    if(!resourceManager->Init())
    {
        std::cout << "The resource manager failed to start. The program will exit." << std::endl;
        exit(1);
    }


    std::cout << "The client starts..." << std::endl;

    // client starts, creates a transaction, does some work on the resource manager and later calls commit

    ITransaction* pTransaction = NULL;
    if( !CreateDTCTransaction(&pTransaction) )
    {
        std::cout << "Failed to create transaction. The program will exit." << std::endl;
        exit(1); // Replace with specific error handling
    }

    byte* txToken = NULL;
    ULONG txTokenSize = 0;
    if( !MarshalDTCTransaction(pTransaction, &txToken, &txTokenSize) )
    {
        std::cout << "Failed to marshal the transaction. The program will exit." << std::endl;
        exit(1); // Replace with specific error handling
    }

    std::cout << "The client asks the resource manager to do work as part of the transaction" << std::endl;
    if( !resourceManager->OpenConnection(txToken, txTokenSize))
    {
        std::cout << "The client failed to open the connection with the resource manager. The program will exit." << std::endl;
        exit(1);
    }
    resourceManager->DoWork();
    resourceManager->CloseConnection();

    std::cout << "The client commits the transaction" << std::endl;
    // Commit the transaction.
    HRESULT hr = S_OK;
    hr = pTransaction->Commit(
    FALSE,                // [in] BOOL fRetaining,
    XACTTC_SYNC_PHASEONE, // [in] DWORD grfTC,
    0                     // [in] DWORD grfRM
    );
    if (FAILED(hr))
    {        
        std::cout << "pTransaction->Commit() failed: Error # " << std::hex << hr << std::endl;
        exit(1); // Replace with specific error handling.
    }
     
    // Release the transaction object.
    pTransaction->Release();
    pTransaction = NULL;

    delete[] txToken;
    txToken = NULL;


    std::cout << std::endl << "The client exits" << std::endl;
    
    // Since the resource manager is sharing its lifetime with the client process in this sample, 
    // to avoid "failed to notify" transactions, we will ask for the user to keep this process alive
    // until the resource manager will complete the transaction
    std::cout << std::endl << "Press ENTER after you see the Resource Manager completing the transaction." << std::endl;
    std::cin.get();

    delete resourceManager;
    resourceManager = NULL;

    return 0;
}
// OpenConnection is called by clients to initiate work with the resource manager under a specified transaction
// The transaction is passed in as a transaction token, to show how transactions objects can be serialized across
// processes
bool DTCResourceManager::OpenConnection(byte* transactionToken, ULONG tokenSize)
{
    std::cout << "The resource manager received an OpenConnection request. Enlisting in the transaction..." << std::endl;
    ITransactionReceiverFactory* pTxReceiverFactory = NULL;
    HRESULT hr = DtcGetTransactionManager(
    NULL,              // [in] char * pszHost,
    NULL,              // [in] char * pszTmName,
    IID_ITransactionReceiverFactory,    // [in] REFIID riid,
    0,                // [in] DWORD dwReserved1,
    0,                // [in] WORD wcbVarLenReserved2,
    (void *)NULL,          // [in] void * pvVarDataReserved2,
    (void **)&pTxReceiverFactory // [out] void ** ppv
    );
    if (FAILED (hr))
    {        
        std::cout << "DtcGetTransactionManager for ITransactionReceiverFactory failed: Error # " << std::hex << hr << std::endl;
        goto cleanup;
    }

    ITransactionReceiver* pTxReceiver = NULL;
    hr = pTxReceiverFactory->Create(&pTxReceiver);
    if (FAILED(hr))
    {        
        std::cout << "pTxReceiverFactory->Create failed: Error # " << std::hex << hr << std::endl;
        goto cleanup;
    }

    ITransaction* pTx = NULL;
    hr = pTxReceiver->UnmarshalPropagationToken(tokenSize, transactionToken, &pTx);
    if (FAILED(hr))
    {        
        std::cout << "pTxReceiver->UnmarshalPropagationToken failed: Error # " << std::hex << hr << std::endl;
        goto cleanup;
    }

    XACTUOW uow;
    LONG isoLevel;

    hr = _pRMManager->Enlist(pTx, this, &uow, &isoLevel, &_pEnlist);
    if (FAILED(hr))
    {        
        std::cout << "pRMManager->Enlist failed: Error # " << std::hex << hr << std::endl;
        goto cleanup;
    }

cleanup:
    if( pTx )
    {
        pTx->Release();
        pTx = NULL;
    }
    if( pTxReceiver )
    {
        pTxReceiver->Release();
        pTxReceiver = NULL;
    }

    if( pTxReceiverFactory )
    {
        pTxReceiverFactory->Release();
        pTxReceiverFactory = NULL;
    }

    if( FAILED(hr) )
    {
        std::cout << "OpenConnection failed" << std::endl;
        return false;
    }
    return true;
}