ZOIS *
Technical Notes
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.
(1) and (2) in the above
example the program can do `stuff', such as interact with the real
user on a terminal.
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
|
tpcommit
|
tpcall DEBIT
ask the user about it
get the users reply
do some other processing
tpcall CREDIT
|
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)
|
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)
|
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
$Date: 2009/12/06 11:17:37 $