11.21 エラーの処理

アプリケーションのロジックは、戻り値がある呼出しのエラー条件を調べ、エラー発生時に適切な処理を行うように設計する必要があります。特に、次を確認します:

  • -1またはNULL値が返されていないかどうかを確認します。どちらの値が返されるかは、呼び出す関数によって異なります。
  • tperrno(5)の値を確認し、その値に応じて適切なアプリケーション・ロジックを実行するswitch文が記述されたコードを呼び出します。

ATMIでは、tpstrerrordetail(3c)tpstrerror(3c)およびFstrerror、Fstrerror32(3fml)の3種類の関数がサポートされており、Oracle TuxedoシステムとFMLのメッセージ・カタログからエラー・メッセージのテキストを取得します。これらの関数は、対応するエラー・メッセージを指すポインタを返します。このポインタを使用して、userlog(3c)などに、ポインタが指すテキストを送ることができます。詳細は、『Oracle Tuxedo ATMI FML関数リファレンス』tpstrerrordetail(3c)tpstrerror(3c)およびFstrerror、Fstrerror32(3fml)に関する項を参照してください。

次のリストは、エラーの一般的な処理方法を示しています。この例では、atmicall()関数は、一般的なATMI呼出しを表しています。switch文(21行目)の後のコードには、アプリケーション定義の戻りコードの解釈にtpurcodeを使用する方法が示されています。

エラー処理のリスト

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     }

tperrno(5)の値は、各問題の詳細を示し、どのレベルで問題の解決が可能かを示しています。アプリケーションで、ある処理に特定のエラー条件が定義されている場合、tpurcodeの値にも同じことが言えます。

次のリストは、tpstrerrordetail(3c)関数を使用して、エラーの発生時に詳細情報を取得する方法を示しています。

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);
}