Transaction Propagation Between an Application Program and a Resource Manager
Transaction propagation between an application program and a resource manager occurs when an application program initiates a transaction, tells the resource manager to enlist in the transaction, and directs the resource manager to do work under the protection of the transaction.
The resource manager is composed of a resource manager server process that manages the resource and a resource manager proxy that implements the application programming interfaces through which application programs invoke resource manager functions. The following illustration shows how resource managers are typically implemented.
The resource manager proxy is commonly implemented as a DLL. When the application program invokes a resource manager function, the proxy validates the input parameters, marshals the parameters into a request message, and sends the request message to the resource manager. When the resource manager receives the request message, it unmarshals the input parameters and performs the requested operation. When the operation is complete, the resource manager marshals the output parameters into a response message and sends the response message to the proxy. The proxy unmarshals the response message and returns the output parameters to the application program.
The resource manager developer must provide the following:
An API that the application program can use to propagate its transaction to the resource manager.
The syntax of the resource manager proxy function that the application uses to pass the transaction to your proxy.
The code to propagate the transaction from the proxy to the resource manager.
The DTC provides an OLE Transactions–compliant export interface that the resource manager proxy uses to marshal a transaction object. The proxy sends the marshaled form of the transaction object to the resource manager. The DTC provides an import interface that the resource manager uses to unmarshal the transaction object. After unmarshaling the transaction object, the resource manager enlists in the transaction.
A database resource manager that uses the standard ODBC syntax for passing a transaction between the application program and the resource manager proxy would work as follows:
The application initiates the transaction by calling the DTC ITransactionDispenser::BeginTransaction method. In response, the application receives a transaction object that represents the transaction.
The application passes the transaction to the proxy by calling the ODBC SQLSetConnectOption statement. The parameters to the SQLSetConnectOption statement include the ODBC connection handle and the transaction object.
The proxy marshals the transaction object by using the DTC ITransactionExport interface. The proxy places the marshaled transaction object into a request message and sends the request message to the resource manager.
The resource manager takes the marshaled transaction object from the request message and unmarshals it by using the DTC ITransactionImport interface, thereby getting a pointer to the transaction object.
The resource manager enlists in the imported transaction object. By enlisting in the transaction, the resource manager enrolls itself in the two-phase commit protocol.
The application program performs normal resource manager operations such as inserting, updating, or deleting records in a relational database. These operations are performed under the protection of the transaction.
When the application program calls Commit, the DTC uses the two-phase commit protocol to coordinate commitment of the transaction. The DTC invokes the resource manager at phase one to prepare the transaction and at phase two to commit the transaction.
You may choose your own application program interface for propagating transactions from the application program to your resource manager. For example, Microsoft SQL Server associates the transaction with the ODBC or DB-Library database connections. The SQLSetConnectOption function is used with ODBC connections, and the dbenlisttrans function is used with DB-Library connections. After a transaction is associated with a connection, it remains associated with the connection until the next SQLSetConnectOption or dbenlisttrans call.
Another alternative, rather than associating a transaction with a connection, would be to insist that the transaction be passed as a parameter to every resource manager call. In this case, you should ensure that you export each transaction only once, when it is first used.
Some resource managers are capable of calling application code from within the resource manager. This permits the application programmer to perform operations that the resource manager and its stored procedure programming language do not directly support. If your resource manager supports this capability, you may choose to provide a way to propagate transactions from your resource manager to the application.
For example, your resource manager could provide a callback that returns the current transaction to the application program. The callback might have an interface such as the following:
HRESULT rm_getthe DTCxact (SRVPROC *srvproc, void **ppv);
This interface returns a pointer to the current transaction object through ppv. If no transaction is active, ppv is null. The interface could return S_OK if successful or E_FAIL on a failure.