BEA Logo BEA Tuxedo Release 7.1

  Corporate Info  |  News  |  Solutions  |  Products  |  Partners  |  Services  |  Events  |  Download  |  How To Buy

 

   Tuxedo Doc Home   |   Programming   |   Topic List   |   Previous   |   Next   |   Contents

   Programming a BEA Tuxedo Application Using C

Starting the Transaction

To start a global transaction, use the tpbegin(3c) function with the following signature.

int
tpbegin(unsigned long timeout, long flags)

The following table describes the arguments to the tpbegin() function.

tpbegin( ) Function Arguments

Field

Description

timeout

Specifies the amount of time, in seconds, a transaction can execute before timing out. You can set this value to the maximum number of seconds allowed by the system, by specifying a value of 0. In other words, you can set timeout to the maximum value for an unsigned long as defined by the system.

The use of 0 or an unrealistically large value for the timeout parameter delays system detection and reporting of errors. The system uses the timeout parameter to ensure that responses to service requests are sent within a reasonable time, and to terminate transactions that encounter problems such as network failures before executing a commit.

For a transaction in which a person is waiting for a response, you should set this parameter to a small value: if possible, less than 30 seconds.

In a production system, you should set timeout to a value large enough to accommodate expected delays due to system load and database contention. A small multiple of the expected average response time is often an appropriate choice.

Note: The value assigned to the timeout parameter should be consistent with that of the SCANUNIT parameter set by the BEA Tuxedo application administrator in the configuration file. The SCANUNIT parameter specifies the frequency with which the system checks, or scans, for timed-out transactions and blocked calls in service requests. The value of this parameter represents the interval of time between these periodic scans, referred to as the scanning unit.

You should set the timeout parameter to a value that is greater than the scanning unit. If you set the timeout parameter to a value smaller than the scanning unit, there will be a discrepancy between the time at which a transaction times out and the time at which this time-out is discovered by the system. The default value for SCANUNIT is 10 seconds. You may need to discuss the setting of the timeout parameter with your application administrator to make sure the value you assign to the timeout parameter is compatible with the values assigned to your system parameters.

flags

Currently undefined; must be set to 0.

Any process may call tpbegin() unless the process is already in transaction mode or is waiting for outstanding replies. If tpbegin() is called in transaction mode, the call fails due to a protocol error and tperrno(5) is set to TPEPROTO. If the process is in transaction mode, the transaction is unaffected by the failure.

The following example provides a high-level view of how a global transaction is defined.

Defining a Global Transaction - High-level View


. . .
if (tpbegin(timeout,flags) == -1)
error routine
program statements
. . .
if (tpcommit(flags) == -1)
error routine


The following example provides a more detailed view of how to define a transaction. This example is excerpted from audit.c, a client program included in bankapp, the sample banking application delivered with the BEA Tuxedo system.

Defining a Global Transaction - Detailed View


#include <stdio.h>         /* UNIX */
#include <string.h> /* UNIX */
#include <atmi.h> /* BEA Tuxedo System */
#include <Uunix.h> /* BEA Tuxedo System */
#include <userlog.h> /* BEA Tuxedo System */
#include "bank.h" /* BANKING #defines */
#include "aud.h" /* BANKING view defines */

#define INVI 0 /* account inquiry */
#define ACCT 1 /* account inquiry */
#define TELL 2 /* teller inquiry */

static int sum_bal _((char *, char *));
static long sitelist[NSITE] = SITEREP; /* list of machines to audit */
static char pgmname[STATLEN]; /* program name = argv[0] */
static char result_str[STATLEN]; /* string to hold results of query */

main(argc, argv)
int argc;
char *argv[];
{
int aud_type=INVI; /* audit type -- invalid unless specified */
int clarg; /* command line arg index from optind */
int c; /* Option character */
int cflgs=0; /* Commit flags, currently unused */
int aflgs=0; /* Abort flags, currently unused */
int nbl=0; /* count of branch list entries */
char svc_name[NAMELEN]; /* service name */
char hdr_type[NAMELEN]; /* heading to appear on output */
int retc; /* return value of sum_bal() */
struct aud *audv; /* pointer to audit buf struct */
int audrl=0; /* audit return length */
long q_branchid; /* branch_id to query */

. . . /* Get Command Line Options and Set Variables */

/* Join application */

if (tpinit((TPINIT *) NULL) == -1) {
(void)userlog("%s: failed to join application\n", pgmname);
exit(1);
}

/* Start global transaction */

if (tpbegin(30, 0) == -1) {
(void)userlog("%s: failed to begin transaction\n", pgmname);
(void)tpterm();
exit(1);
}

if (nbl == 0) { /* no branch id specified so do a global sum */
retc = sum_bal(svc_name, hdr_type); /* sum_bal routine not shown */

} else {

/* Create buffer and set data pointer */

if ((audv = (struct aud *)tpalloc("VIEW", "aud", sizeof(struct aud)))
== (struct aud *)NULL) {
(void)userlog("audit: unable to allocate space for VIEW\n");
exit(1);
}

/* Prepare aud structure */

audv->b_id = q_branchid;
audv->balance = 0.0;
audv->ermsg[0] = '\0';

/* Do tpcall */

if (tpcall(svc_name,(char *)audv,sizeof(struct aud),
(char **)audv,(long *)audrl,0) == -1){
(void)fprintf (stderr,"%s service failed\n%s: %s\n",
svc_name, svc_name, audv->ermsg);
retc = -1;

}else {

(void)sprintf(result_str,"Branch %ld %s balance is $%.2f\n",
audv->b_id, hdr_type, audv->balance);
}
tpfree((char *)audv);
}

/* Commit global transaction */

if (retc < 0) /* sum_bal failed so abort */
(void) tpabort(aflgs);
else {
if (tpcommit(cflgs) == -1) {
(void)userlog("%s: failed to commit transaction\n", pgmname);
(void)tpterm();
exit(1);
}
/*print out results only when transaction has committed successfully*/
(void)printf("%s",result_str);
}

/* Leave application */

if (tpterm() == -1) {
(void)userlog("%s: failed to leave applicati

If a transaction times out, a call to tpcommit() causes the transaction to be aborted. As a result, tpcommit() fails and sets tperrno(5) to TPEABORT.

The following example shows how to test for a transaction time-out. Note that the value of timeout is set to 30 seconds.

Testing for Transaction Time-out


if (tpbegin(30, 0) == -1) {
(void)userlog("%s: failed to begin transaction\n", argv[0]);
tpterm();
exit(1);
}
. . .
communication calls
. . .
if (tperrno == TPETIME){
if (tpabort(0) == -1) {
check for errors;
}
else if (tpcommit(0) == -1){
check for errors;
}
. . .


Note: When a process is in transaction mode and makes a communication call with flags set to TPNOTRAN, it prohibits the called service from becoming a participant in the current transaction. Whether the service request succeeds or fails has no impact on the outcome of the transaction. The transaction can still time-out while waiting for a reply that is due from a service, whether it is part of the transaction or not. Refer to Managing Errors for more information on the effects of the TPNOTRAN flag.