Implementing DTC Interfaces
To work with the DTC, a resource manager needs to implement only the IResourceManagerSink and ITransactionResourceAsync interfaces.
IResourceManagerSink is required for building a relationship between the resource manager and the transaction coordinator.
ITransactionResourceAsync is required for receiving the two-phase notifications for a transaction in which the resource manager is enlisted. There is one instance of ITransactionResourceAsync per enlistment. Typically, there is one enlistment per transaction, but a resource manager can choose to enlist multiple times in the same transaction.
A resource manager generally follows these steps:
Establishing a Relationship with the DTC
The resource manager calls the DtcGetTransactionManager function to get a reference to the IUnknown interface on the DTC proxy core object. Using this reference, the resource manager can call QueryInterface for IResourceManagerFactory and then calls IResourceManagerFactory::Create for a reference to the resource manager object'sIResourceManager interface, which the resource manager uses to enlist in new transactions and to perform recovery.
Enlisting in New Transactions
After it establishes a relationship with the DTC, the resource manager can obtain a transaction's ITransaction interface and enlist in this transaction by invoking IResourceManager::Enlist. One of this method's parameters is an instance of ITransactionResourceAsync.
When the initiator of the transaction invokes ITransaction::Commit, the DTC initiates the voting phase of the two-phase commit protocol. The first phase notification is delivered to the enlisted resource manager by invoking ITransactionResourceAsync::PrepareRequest. The resource manager then performs the relevant work to move from an active state to a prepared state and, on moving to the prepared state, invokes ITransactionEnlistmentAsync::PrepareRequestDone.
The decision phase notification is provided to each enlisted participant by the invocation of ITransactionResourceAsync::CommitRequest. A resource manager responds to this notification by invoking ITransactionEnlistmentAsync::CommitRequestDone.
The Abort notification works the same way as the first phase notification but with no second phase.
Note |
|---|
| Application code (such as a stored procedure) may exist in-process with a resource manager. This application code could obtain a DTC transaction, and because it is in-process with the resource manager, it could provide a reference to the ITransaction interface on the transaction object to the resource manager, which then can enlist in that transaction. |
Performing Recovery
The recovery process consists of the following two steps:
-
The resource manager examines the log file to identify all the prepare information records for transactions that are in-doubt. For each such transaction, it invokes IResourceManager::Reenlist, which provides the outcome for that transaction. If the DTC doesn't know the transaction outcome, Reenlist fails with an XACT_E_REENLISTTIMEOUT error message, in which case the resource manager will need to retry at a later time.
-
The resource manager invokes IResourceManager::ReenlistmentComplete when the resource manager learns the outcome for all the in-doubt transactions. This method completes the recovery and informs the DTC that the resource manager has no more in-doubt transactions. By invoking, the resource manager guarantees that it will not invoke the Reenlist method again.
A resource manager to is not required to resolve all in-doubt transactions before enlisting in new transactions. Step 1 can be performed at any time after the resource manager establishes a relationship with the DTC, but after ReenlistmentComplete has been invoked (step 2), step 1 cannot be performed again. Step 2 can be repeated multiple times without affecting the outcome of transactions.
Note