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; }