11.21 Handling Errors
Your application logic must test for error conditions for the calls that have return values, and take appropriate action when an error occurs. Specifically, you must:
- Test to determine whether a
-1
orNULL
value has been returned (depending on the function call). - Invoke code that contains a switch statement that tests for specific values of
tperrno(5)
and performs the appropriate application logic.
The ATMI supports three functions, tpstrerrordetail(3c)
, tpstrerror(3c)
, and Fstrerror, Fstrerror32(3fml)
, for retrieving the text of an error message from the message catalogs for the Oracle Tuxedo system and FML. The functions return pointers to the appropriate error messages. Your program can use a pointer to direct the referenced text to userlog(3c)
or to another destination. For details, refer to tpstrerrordetail(3c)
and tpstrerror(3c)
, and Fstrerror, Fstrerror32(3fml)
in the Oracle Tuxedo ATMI FML Function Reference.
The following listing shows a typical method of handling errors. The atmicall()
function in this example represents a generic ATMI call. Note the code after the switch statement (line 21): it shows how tpurcode
can be used to interpret an application-defined return code.
Listing Handling Errors
001 #include <stdio.h>
002 #include "atmi.h"
003
004 main()
005
006 {
007 int rtnval;
008
009 if (tpinit((TPINIT *) NULL) == -1)
010 error message, exit program;
011 if (tpbegin(30, 0) == -1)
012 error message, tpterm, exit program;
013
014 allocate any buffers,
015 make atmi calls
016 check return value
017
018 rtnval = atmicall();
019
020 if (rtnval == -1) {
021 switch(tperrno) {
022 case TPEINVAL:
023 fprintf(stderr, "Invalid arguments were given to atmicall\n");
024 fprintf(stderr, "e.g., service name was null or flags wrong\n");
025 break;
026 case ...:
027 fprintf(stderr, ". . .");
028 break;
029
030 Include all error cases described in the atmicall(3) reference 031
page.
032 Other return codes are not possible, so there should be no 033 default
within the switch statement.
034
035 if (tpabort(0) == -1) {
036 char *p;
037 fprintf(stderr, "abort was attempted but failed\n");
038 p = tpstrerror(tperrno);
039 userlog("%s", p);
040 }
041 }
042 else
043 if (tpcommit(0) == -1)
044 fprintf(stderr, "REPORT program failed at commit time\n");
045
046 The following code fragment shows how an application-specific
047 return code can be examined.
048 .
049 .
050 .
051 ret = tpcall("servicename", (char*)sendbuf, 0, (char **)&rcvbuf,
&rcvlen, \
052 (long)0);
053 .
054 .
055 .
056 void) fprintf(stdout, "Returned tpurcode is: %d\n", tpurcode);
057
058
059 free all buffers
060 tpterm();
061 exit(0);
062 }
The values of tperrno(5)
provide details about the nature of each problem and suggest the level at which it can be corrected. If your application defines a list of error conditions specific to your processing, the same can be said for the values of tpurcode
.
The following listing shows how to use the tpstrerrordetail(3c)
function to obtain additional detail when an error is encountered.
Listing Handling Errors Using tpstrerrordetail( )
001 #include <stdio.h>
002 #include <string.h>
003 #include <atmi.h>/* ORACLE Tuxedo Header File */
004 #define LOOP_ITER 100
005 #if defined(__STDC__) || defined(__cplusplus)
006 main(int argc, char *argv[])
007 #else
008 main(argc, argv)
009 int argc;
010 char *argv[];
011 #endif
012 {
013 char *sendbuf, *rcvbuf;
014 long sendlen, rcvlen;
015 int ret;
016 int i;
017 if(argc != 2) {
018 (void) fprintf(stderr, "Usage: simpcl string\n");
019 exit(1);
020 }
021 /* Attach to ORACLE Tuxedo System as a Client Process */
022 if (tpinit((TPINIT *) NULL) == -1) {
023 (void) fprintf(stderr, "Tpinit failed\n");
024 exit(1);
025 }
026 sendlen = strlen(argv[1]);
027
028 /* Allocate STRING buffers for the request and the reply */
029
030 if((sendbuf = (char *) tpalloc("STRING", NULL, sendlen+1)) == NULL) {
031 (void) fprintf(stderr,"Error allocating send buffer\n");
032 tpterm();
033 exit(1);
034 }
035
036 if((rcvbuf = (char *) tpalloc("STRING", NULL, sendlen+1)) == NULL) {
037 (void) fprintf(stderr,"Error allocating receive buffer\n");
038 tpfree(sendbuf);
039 tpterm();
040 exit(1);
041 }
042
043 for( i=0; i<LOOP_ITER; i++) {
044 (void) strcpy(sendbuf, argv[1]);
045
046 /* Request the service TOUPPER, waiting for a reply */
047 ret = tpcall("TOUPPER", (char *)sendbuf, 0, (char **)&rcvbuf,
&rcvlen, (long)0);
048
049 if(ret == -1) {
050 (void) fprintf(stderr, "Can't send request to service
TOUPPER\n");
051 (void) fprintf(stderr, "Tperrno = %d, %s\n", tperrno,
tpstrerror(tperrno));
052
053 ret = tperrordetail(0);
054 if(ret == -1) {
055 (void) fprintf(stderr, "tperrodetail() failed!\n");
056 (void) fprintf(stderr, "Tperrno = %d, %s\n", tperrno,
tpstrerror(tperrno));
057 }
058 else if (ret != 0) {
059 (void) fprintf( stderr, "errordetail:%s\n",
060 tpstrerrordetail( ret, 0));
061 }
062 tpfree(sendbuf);
063 tpfree(rcvbuf);
064 tpterm();
065 exit(1);
066 }
067 (void) fprintf(stdout, "Returned string is: %s\n", rcvbuf);
068 }
069
070 /* Free Buffers & Detach from System/T */
071 tpfree(sendbuf);
072 tpfree(rcvbuf);
073 tpterm();
074 return(0);
}
Parent topic: Managing Errors