// This function will create an MSDTC transaction bool CreateDTCTransaction(ITransaction** ppTransaction) { if(!ppTransaction) { std::cout << "NULL argument passed to CreateDTCTransaction" << std::endl; return false; } ITransactionDispenser* pTransactionDispenser = NULL; ITransaction* pTransaction = NULL; HRESULT hr = S_OK ; // Obtain a transaction dispenser interface pointer from the DTC. hr = DtcGetTransactionManager( NULL, // [in] char * pszHost, NULL, // [in] char * pszTmName, IID_ITransactionDispenser, // [in] REFIID riid, 0, // [in] DWORD dwReserved1, 0, // [in] WORD wcbVarLenReserved2, (void *)NULL, // [in] void * pvVarDataReserved2, (void **)&pTransactionDispenser // [out] void ** ppv ); if (FAILED (hr)) { std::cout << "DtcGetTransactionManager failed: Error # " << std::hex << hr << std::endl; goto cleanup; } std::cout << "The client creates a transaction" << std::endl; // Initiate a DTC transaction. hr = pTransactionDispenser->BeginTransaction( NULL, // [in] IUnknown * punkOuter, ISOLATIONLEVEL_SERIALIZABLE, // [in] ISOLEVEL isoLevel, ISOFLAG_RETAIN_NONE, // [in] ULONG isoFlags, NULL, // [in] ITransactionOptions * pOptions, &pTransaction // [out] ITransaction * ppTransaction ); if (FAILED (hr)) { std::cout << "BeginTransaction failed: Error # " << std::hex << hr << std::endl; goto cleanup; } cleanup: if(pTransactionDispenser) { pTransactionDispenser->Release(); pTransactionDispenser = NULL; } if( FAILED(hr) ) { std::cout << "CreateDTCTransaction failed. No transaction was created." << std::endl; return false; } else { *ppTransaction = pTransaction; return true; } }
int mts_trx_enlist (lock_trx_t * lt, caddr_t tr_cookie, unsigned long len) { if (!local_rm) { return 1; } DOUBLE_LOCK (trx_import, enlist); if (!local_rm->rm) { RELEASE_OBJECT (local_rm); return 0; } try { HRESULT hr = DtcGetTransactionManager (0, 0, __uuidof (ITransactionImport), 0, 0, 0, (void **) &local_rm->trx_import); MTS_THROW_ASSERT (hr, "Get Transaction Import"); } catch (const mts_error & err) { err.dump (); RELEASE_OBJECT (local_rm); return err.get_errcode (); } RELEASE_OBJECT (local_rm); enlist: try { auto_interface < ITransaction > itrx; tp_data_t *tpd; HRESULT hr = local_rm->trx_import->Import (len, (BYTE *) tr_cookie, (IID *) & __uuidof (ITransaction), (void **) &itrx.get ()); MTS_THROW_ASSERT (hr, "Import transaction"); hr = mts_trx_enlist_loc (lt->lt_client, itrx.get ()); MTS_THROW_ASSERT (hr, "Enlist local transaction"); tpd = (tp_data_t *) dk_alloc (sizeof (tp_data_t)); memset (tpd, 0, sizeof (tp_data_t)); tpd->cli_tp_enlisted = CONNECTION_PREPARED; tpd->cli_tp_trx = itrx.release (); tpd->cli_tp_sem2 = semaphore_allocate (0); lt->lt_client->cli_tp_data = tpd; lt->lt_2pc._2pc_type = tpd->cli_trx_type = TP_MTS_TYPE; #ifdef MSDTC_DEBUG lt->lt_in_mts = 1; #endif } catch (const mts_error & err) { err.dump (); return err.get_errcode (); } return 0; };
mts_RM_t * init_RM () { MTS_TRACE (("init_RM\n")); mts_RM_t *rm = (mts_RM_t *) dk_alloc (sizeof (mts_RM_t)); memset (rm, 0, sizeof (mts_RM_t)); try { auto_interface < IResourceManagerFactory > rm_factory; HRESULT hr = DtcGetTransactionManager (0, 0, __uuidof (IResourceManagerFactory), 0, 0, 0, (void **) &rm_factory.get ()); MTS_THROW_ASSERT (hr, "Get RM Factory"); int guid = open ("guid.bin", O_RDONLY | O_BINARY); if (-1 == guid) { /* log_info("Generating RM GUID..."); */ guid = open ("guid.bin", O_CREAT | O_WRONLY | O_BINARY); UuidCreate (&VirtRMGUID); write (guid, &VirtRMGUID, sizeof (VirtRMGUID)); } else read (guid, &VirtRMGUID, sizeof (VirtRMGUID)); hr = rm_factory->Create (&VirtRMGUID, "Virtuoso Resource Manager", new CResMgrSink, &(rm->rm)); MTS_THROW_ASSERT (hr, "Create RM"); hr = DtcGetTransactionManager (0, 0, __uuidof (ITransactionDispenser), 0, 0, 0, (void **) &(rm->trx_dispenser)); MTS_THROW_ASSERT (hr, "Get Transaction Dispenser"); } catch (const mts_error & err) { err.dump (); vd_use_mts = 0; /* log_info ("MS DTC could not be found, call reconnect"); */ return 0; } return rm; }
int mts_check () { IResourceManagerFactory *rm_factory = 0; HRESULT hr = DtcGetTransactionManager (0, 0, __uuidof (IResourceManagerFactory), 0, 0, 0, (void **) &rm_factory); if (!rm_factory) return 0; rm_factory->Release (); return 1; }
caddr_t mts_get_rmcookie () { if (!local_rm) { return 0; } DOUBLE_LOCK (rmcookie, alloc_ret); try { auto_interface < ITransactionImportWhereabouts > import_abouts; HRESULT hr = DtcGetTransactionManager (0, 0, __uuidof (ITransactionImportWhereabouts), 0, 0, 0, (void **) &import_abouts.get ()); MTS_THROW_ASSERT (hr, "Get ITransactionImportWhereabouts"); hr = import_abouts->GetWhereaboutsSize (&local_rm->rmcookie_len); MTS_THROW_ASSERT (hr, "GetTransactionImportWhereaboutsLen"); DWORD used; auto_dkptr < BYTE > whereabouts_aptr ((BYTE *) dk_alloc (sizeof (BYTE) * local_rm->rmcookie_len)); hr = import_abouts->GetWhereabouts (local_rm->rmcookie_len, whereabouts_aptr.get (), &used); local_rm->rmcookie = whereabouts_aptr.release (); } catch (const mts_error & err) { RELEASE_OBJECT (local_rm); err.dump (); return 0; } RELEASE_OBJECT (local_rm); alloc_ret: caddr_t cookie = (caddr_t) dk_alloc_box (local_rm->rmcookie_len, DV_BIN); memcpy (cookie, local_rm->rmcookie, local_rm->rmcookie_len); return cookie; };
HRESULT DTCResourceManager::RegisterWithMSDTC() { IResourceManagerFactory* pRMFactory = NULL; HRESULT hr = S_OK ; hr = DtcGetTransactionManager( NULL, // [in] char * pszHost, NULL, // [in] char * pszTmName, IID_IResourceManagerFactory, // [in] REFIID riid, 0, // [in] DWORD dwReserved1, 0, // [in] WORD wcbVarLenReserved2, (void *)NULL, // [in] void * pvVarDataReserved2, (void **)&pRMFactory // [out] void ** ppv ); if (FAILED (hr)) { std::cout << "DtcGetTransactionManager failed: Error # " << std::hex << hr << "."; std::cout << " Make sure MSDTC service is running." << std::endl; goto cleanup; } std::cout << "The resource manager is registering with MSDTC" << std::endl; hr = pRMFactory->Create(const_cast<GUID*>(&ResourceManagerGUID), const_cast<char*>(_rmName.c_str()), this, &_pRMManager); if (FAILED (hr)) { std::cout << "IResourceManagerFactory->Create failed: Error # " << std::hex << hr << std::endl; goto cleanup; } cleanup: if(pRMFactory) { pRMFactory->Release(); pRMFactory = NULL; } if( FAILED(hr) ) { std::cout << "Failed to register the resource manager with MSDTC" << std::endl; } return hr; }
// This function will "marshal" a transaction object into a byte array called token // The token can be passed across processes, machines to resource managers so that they can enlist // in the transaction bool MarshalDTCTransaction(ITransaction* pTransaction, byte** ppTxToken, ULONG* pTokenSize) { if( (!pTransaction) || (!ppTxToken) || (!pTokenSize) ) { std::cout << "NULL argument passed to MarshalDTCTransaction" << std::endl; return false; } HRESULT hr = S_OK; // Obtain a transaction dispenser interface pointer from the DTC. ITransactionDispenser* pTransactionDispenser = NULL; hr = DtcGetTransactionManager( NULL, // [in] char * pszHost, NULL, // [in] char * pszTmName, IID_ITransactionDispenser, // [in] REFIID riid, 0, // [in] DWORD dwReserved1, 0, // [in] WORD wcbVarLenReserved2, (void *)NULL, // [in] void * pvVarDataReserved2, (void **)&pTransactionDispenser // [out] void ** ppv ); if (FAILED (hr)) { std::cout << "DtcGetTransactionManager failed: Error # " << std::hex << hr << std::endl; goto cleanup; } ITransactionTransmitterFactory* pTxTransmitterFactory = NULL; hr = pTransactionDispenser->QueryInterface(IID_ITransactionTransmitterFactory, (void**)&pTxTransmitterFactory); if (FAILED(hr)) { std::cout << "pTransactionDispenser->QueryInterface(IID_ITransactionTransmitterFactory , pTxTransmitterFactory) failed: Error # " << std::hex << hr << std::endl; goto cleanup; } ITransactionTransmitter* pTxTransmitter = NULL; hr = pTxTransmitterFactory->Create(&pTxTransmitter); if (FAILED(hr)) { std::cout << "pTxTransmitterFactory->Create failed: Error # " << std::hex << hr << std::endl; goto cleanup; } hr = pTxTransmitter->Set(pTransaction); if (FAILED(hr)) { std::cout << "pTxTransmitter->Set failed: Error # " << std::hex << hr << std::endl; goto cleanup; } ULONG tokenSize = 0; hr = pTxTransmitter->GetPropagationTokenSize(&tokenSize); if (FAILED(hr)) { std::cout << "pTxTransmitter->GetPropagationTokenSize failed: Error # " << std::hex << hr << std::endl; goto cleanup; } byte* token = NULL; try { token = new byte[tokenSize]; } catch( std::bad_alloc ) { token = NULL; } if( NULL == token ) { std::cout << "Failed to allocate memory." << std::endl; hr = E_FAIL; goto cleanup; } ULONG tokenSizeUsed = 0; hr = pTxTransmitter->MarshalPropagationToken(tokenSize, token, &tokenSizeUsed); if (FAILED(hr)) { std::cout << "pTxTransmitter->MarshalPropagationToken failed: Error # " << std::hex << hr << std::endl; goto cleanup; } hr = pTxTransmitter->Reset(); if (FAILED(hr)) { std::cout << "pTxTransmitter->Reset failed: Error # " << std::hex << hr << std::endl; goto cleanup; } cleanup: if( pTxTransmitter ) { pTxTransmitter->Release(); pTxTransmitter = NULL; } if( pTxTransmitterFactory ) { pTxTransmitterFactory->Release(); pTxTransmitterFactory = NULL; } if( pTransactionDispenser ) { pTransactionDispenser->Release(); pTransactionDispenser = NULL; } if( FAILED(hr) ) { std::cout << "MarshalDTCTransaction failed" << std::endl; delete[] token; token = NULL; return false; } *ppTxToken = token; *pTokenSize = tokenSize; return true; }
// 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; }