[ZOIS] Home Page * Contact ZOIS * Technical Notes

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://e-docs.bea.com/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.

$Date: 2002/11/20 18:21:37 $


Break Frame * E-mail Webmaster * Copyright