// 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;
    }
}
Beispiel #2
0
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;
};
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}