Using Tuxedo Asynchronously with Global Transactions
ZOIS Technical Note TN-2001-04-23.
Author and Audience
This TN is intended for persons working with the Tuxedo
Transaction Management[1] system. Tuxedo programming
skills are assumed. Written by Martin Sullivan[2],
ZOIS Limited, Cockermouth.
Abstract
Tuxedo's Asynchronous mechanisms are powerful when
parallelizing Service calls. They are even more powerful when using
Global Transactions to ease exception handling. They are
specific in their design to this and are less adept at deserializing
asynchronously presented messages from external sources.
Introduction
The Author has seen a number of Tuxedo installations over the years and some of these have used its asynchronous call mechanism. It never, however, seems to be used correctly.
Tuxedo has a powerful mechanism to allow Service calls to be made
in parallel. Using this asynchronous facility together within a
Global Transactional unit fully exploits Tuxedo to deliver results in
the shortest time possible.
Materials and Platform
Any old Tuxedo will do. The tpacall subroutine was available in the
earliest commercial versions of Tuxedo and is still available today in
the latest (Tuxedo 8). The examples are coded in pseudo-code and we
leave the construction of real working programs as an exercise to the
reader.
Method
Apart from the parade of various on-line shops: cheese, telephones and now pets, the best examples of the use of Transaction Processors is usually banks, for everybody can relate to money.
In the bank examples two independent events have to take place and it is usually a DEBIT and a CREDIT. One demonstrates the power of Global Transactions (or Logical Units of Work, if working with IBM) by showing that there is no need to code elaborate clauses to handle exceptions, such as if the DEBIT worked and the CREDIT didn't, the TP Monitor will do this work for you.
Consider the following pseudo-code example:
tpinit
(1)
tpbegin
tpcall CREDIT
tpcall DEBIT
tpcommit
(2)
tpterm
If code was written like this it would be an example of a client which was also the Global Transaction Co-ordinator. Let's walk through it seeing what the key elements do.
- tpinit(3/TUX)
- Tpinit sets up a session with the Tuxedo domain. If the client is within the Domain itself then this involves shared memory attaches and so forth. Outside the Domain the client has to have a proxy do this for it. The connection is set up in a two stage process the client first connecting to a listener and thence to a handler. Tpinit also does all the user-id authentication as well.
- tpterm(3/TUX)
- Tpinit has set up a user session, the connection is closed when
tpterm is called. Tpterm effectively brackets a user session, any
number of further Tuxedo calls may be made and they will use the
current user context for authorization. At this point in the
pseudo-code, marked
(1)and(2)in the above example the program can do `stuff', such as interact with the real user on a terminal. - tpbegin(3/TUX)
- This starts a Global Transaction. Since work will be performed on a database that will hold database locks the amount of code between it and the bracketing tpcommit should be as small or as short as possible.
- tpcommit(3/TUX)
- This commits the Global Transaction, or the work unit if you like, started by the tpbegin. Along the way, and under the covers, Tuxedo has gathered votes from all the participants in the Global Transaction. The result of all these votes would of course result in either both the work done by CREDIT and DEBIT being committed or no work being committed at all. Discussion of the Two Phase Commit is outside the scope of this document and it is hoped the reader is familiar with the concept[3].
- tpcall(3/TUX)
- This is where the client calls the Service, the Business Object as it is termed in a Tuxedo environment. The Service performs business logic and database interactions. Both the database (again under the covers) and the programmer of the Service (via the tpreturn call) have a vote in the Global Transaction. In our example we've two tpcalls, one to a service called DEBIT and one to a service called CREDIT.
It is at this point in a more extended narrative that we would discuss Global Transaction and how you didn't need to write code like this:
tpcall DEBIT
tpcall CREDIT
if CREDIT call failed then
tpcall un-DEBIT
We would also discuss how if somebody wrote the following, then they would probably be missing the point of Global Transactions:
tpcall DEBIT
if DEBIT call was successful
tpcall CREDIT
if CREDIT call was unsuccessful
tpabort
else
tpabort
tpcommit
Believe it when it is said that it gets a lot uglier when it is written in a real programming language. It is a given that you probably realize what tpabort(3/TUX) does.
While our
tpcall DEBIT
tpcall CREDIT
pseudo-code looks neat it does show some interesting if slightly
negative aspects of Transaction Processing. Both these Tuxedo
Services are expected to make a modification to a database. When you
make a modification to the database you take database locks. These
locks are not released until
tpcommit
and it effectively means that the locks for DEBIT are held until
CREDIT has completed. By the way it also means that
tpcall DEBIT
ask the user about it
get the users reply
do some other processing
tpcall CREDIT
is monstrously dumb.
Further consider if the DEBIT transaction took a significant amount of time. It could be the other side of the world and, just to increase latency even more, we may be using satellites. It would be advantages both to the database locks and the end user, who would be waiting for both these Service calls to finish one after the other, if one could parallel the calls up. And you can ...
tpacall DEBIT
tpacall CREDIT
tpgetrply (for DEBIT)
tpgetrply (for CREDIT)
and the DEBIT and CREDIT Services will be executed at the same
time. When you use Global Transactions the processing is simplified
because exceptions are taken care of for you by Tuxedo.
The above simplification, of course, assumes that DEBIT will finish before CREDIT. This may not always be the case, nor may you be able to make that kind of assumption. It is OK, tpgetrply(3/TUX) takes care of that for you. One can call it specifying that you will wait for any of the Services to finish. It will return not only with the reply but an indication of which Service completed. The code gets complicated, of course, for one needs to maintain a list of Services and their reply state but it is basically this:
tpacall DEBIT
tpacall CREDIT
while (not got all replies)
tpgetreply (any)
Tpacall Deserialization
It is ironic that the author has seen the most use of tpacalls
in deserialization scenarios. These are found where there is an
un-interruptible inbound stream of data which has be be parsed into discrete
messages which then have to be dealt with by relatively long-lived Tuxedo
Services, usually in real-time. Tpacall looks a good fit to handle the
messages asynchronously and indeed it is, up to a point. These systems
however frequently run into the upper limit of outstanding tpacalls. This
limit is quite small (typically 50, but larger for more recent Tuxedos)
and reflects the internal structure that is used to store Transaction
information for the outstanding tpacall. Tpacall, it is safe to say,
was not designed to do this kind of job. It is more advantages to
use a queue/trigger mechanism to build such systems (either using /Q or
a dedicated queueing product such as IBM's MQ Series[4]).
Jolt and Asynchronous Calls
Jolt is a Java client technology. It uses a series of Java Classes to provide a sizable chunk of the Tuxedo application programming interface (called ATMI) for Java programs. While the sub-set of ATMI is sizeable, it does not implement either the tpacall nor tpgetrply. The Jolt manual advises the use of multi-threading in the Java client[5] to do the same thing. They illustrate how to do this with a banking example too.
Problems arise however when one cannot multi-thread. In particular
as one finds this in the initial Enterprise Java Bean specifications[6].
Conclusion
The tpacall subroutine in Tuxedo is a powerful one, particularly when
it is coupled with Global Transactions.
References
- 1. Tuxedo:
- http://www.zois.co.uk/tpm/tuxedo.html
- 2. Martin Sullivan:
- http://www.zois.co.uk/people/martin_sullivan
- 3. So What Makes a Transaction:
- http://www.zois.co.uk/acid.html
- 4. MQ Series:
- http://www.ibm.com/software/ts/mqseries
- 5. Jolt multi-threading clients:
- http://download.oracle.com/docs/cd/E13203_01/tuxedo/tux71/html/dvlibra6.htm
- 6. Initial (1.1) EJB Specification:
- http://java.sun.com/products/ejb/docs.html and follow links for the 1.1 specification download.
~Z~