|
|
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
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.
Copyright © 2000 BEA Systems, Inc. All rights reserved.
Required browser: Netscape 4.0 or higher, or Microsoft Internet Explorer 4.0 or higher.