Performing Recovery
A resource manager facilitates resolution of durable enlistments in a transaction by reenlisting the transaction participant after resource failure.
To durably enlist a resource (described by an implementation of the IEnlistmentNotification interface) that can later be eligible for recovery, you should call the EnlistDurable method. In addition, you must provide the EnlistDurable method with a resource manager identifier (a Guid) that is used to consistently label the participant of the transaction in the event of a resource failure. For this reason, the Guid that is provided to the initial Enlist call should be identical to the resourceManagerIdentifier parameter in the Reenlist call during recovery. Otherwise, TransactionException is thrown. For more information on durable enlistments, see Enlisting Resources as Participants in a Transaction .
In the prepare phase (phase 1) of the 2PC protocol, when your implementation of a durable resource manager receives the Prepare notification, it should log its prepare record during this phase. The record should contain all the information that is necessary to complete the transaction on commit. The prepare record can later be accessed during recovery by retrieving the RecoveryInformation property of the preparingEnlistment callback. The record logging does not need to be performed within the Prepare method as the RM can do this on a worker thread.
The recovery process consists of the following two steps:
The resource manager examines the prepare information record for each enlistment that is in-doubt. This is done by examining the RecoveryInformation property of the PreparingEnlistment callback, which is passed to the resource manager in the Prepare notification during phase 1.
For each such enlistment it examines, it invokes Reenlist on the transaction manager. This method passes on a unique Guid that identifies the resource manager, as well as the enlistment's information in a byte array. A new Enlistment object is returned. If the reenlistment fails with an exception, the resource manager will need to retry at a later time.
You should only call the Reenlist method when a resource manager restarts from failure. In addition, you should only reenlist unresolved transactions logged by a resource manager during the initial Prepare phase of a two-phase commit. Any attempt to call this method at invalid times can produce erroneous results.
When a participant is reenlisted using this method, the phase 2 methods of IEnlistmentNotification that correspond to the transaction's outcome (that is, Commit , Rollback or InDoubt ) are called as appropriate.
When all the reenlistments are finished, the resource manager calls the RecoveryComplete method. This method completes the recovery and informs the transaction manager that the resource manager has no more in-doubt transactions. By doing so, the resource manager guarantees that it will not invoke the Reenlist method again.
A resource manager is not required to resolve all in-doubt transactions before enlisting in new transactions. The first step can be performed at any time after the resource manager establishes a relationship with the transaction manager, but after RecoveryComplete has been invoked (step 2); step 1 cannot be performed again. Step 2 can be repeated multiple times without affecting the outcome of transactions.