11.33 全般的なサンプル・コード
トランザクションの整合性、メッセージの通信、およびリソースへのアクセスは、オンライン・トランザクション処理(OLTP)アプリケーションの主要な要件です。
ここでは、リソース・マネージャにアクセスするSQL文と共に動作する通信ルーチン、バッファ管理、ATMIトランザクションを示すサンプル・コードを示します。ここで示す例は、Oracle Tuxedo銀行業務アプリケーション(bankapp
)のACCT
サーバーから抜粋したCLOSE_ACCT
サービスです。
この例は、最初のSQL文でデータベースにアクセスする前に、set transaction
文(49行目)を使用して、トランザクションの整合性レベルとアクセス・モードを設定する方法を示しています。(読取り/書込みの権限が指定されている場合、整合性レベルはデフォルトで高い整合性に設定されます。)ACCOUNT_ID
の値に基づいて口座を解約するために、SQL問合せで引出し額を決定します(50 - 58行目)。
tpalloc()
は、WITHDRAWAL
サービスへのリクエスト・メッセージ用のバッファを割り当て、ACCOUNT_ID
と引出し額がバッファに格納されます(62 - 74行目)。次に、tpcall()
呼出しを介してWITHDRAWAL
サービスにリクエストが送信されます(79行目)。その後、SQLのdelete
文で、該当する口座を削除してデータベースを更新します(86行目)。
すべての処理が成功すると、サービス内で割り当てられたバッファが解放され(98行目)、サービスに送信されたTPSVCINFO
データ・バッファが更新されて、トランザクションが正常に終了したことが示されます(99行目)。サービスがイニシエータであった場合、ここでトランザクションが自動的にコミットされます。tpreturn()
は、口座の解約を要求したクライアント・プロセスに、TPSUCCESS
と更新後のバッファを返します。最後に、要求されたサービスが正常に終了したことが、フォームのステータス行に示されます。
各関数呼出しの後、成功したか失敗したかが確認されます。エラーが発生した場合、サービスで割り当てられたバッファが解放され、サービスで開始されたトランザクションが中断され、TPSVCINFO
バッファが更新されてエラーの原因が示されます(80 - 83行目)。最後に、tpreturn()
がTPFAIL
を返し、更新されたバッファ内のメッセージがフォームのステータス行に表示されます。
ノート:
サービス・ルーチンでグローバル・トランザクションの整合性レベルを指定する場合、同じトランザクションに参加するすべてのサービス・ルーチンで、同じようにレベルを定義する必要があります。ACCTサーバーのリスト
001 #include <stdio.h> /* UNIX */
002 #include <string.h> /* UNIX */
003 #include <fml.h> /* ORACLE Tuxedo System */
004 #include <atmi.h> /* ORACLE Tuxedo System */
005 #include <Usysflds.h> /* ORACLE Tuxedo System */
006 #include <sqlcode.h> /* ORACLE Tuxedo System */
007 #include <userlog.h> /* ORACLE Tuxedo System */
008 #include "bank.h" /* BANKING #defines */
009 #include "bank.flds.h" /* bankdb fields */
010 #include "event.flds.h" /* event fields */
011
012
013 EXEC SQL begin declare section;
014 static long account_id; /* account id */
015 static long branch_id; /* branch id */
016 static float bal, tlr_bal; /* BALANCE */
017 static char acct_type; /* account type*/
018 static char last_name[20], first_name[20]; /* last name, first name */
019 static char mid_init; /* middle initial */
020 static char address[60]; /* address */
021 static char phone[14]; /* telephone */
022 static long last_acct; /* last account branch gave */
023 EXEC SQL end declare section;
024 static FBFR *reqfb; /* fielded buffer for request message */
025 static long reqlen; /* length of request buffer */
026 static char amts[BALSTR]; /* string representation of float */
027 code for OPEN_ACCT service
028 /*
029 * Service to close an account
030 */
031 void
032 #ifdef __STDC__
033 LOSE_ACCT(TPSVCINFO *transb)
034 #else
035 CLOSE_ACCT(transb)
036 TPSVCINFO *transb;
037 #endif
038 {
039 FBFR *transf; /* fielded buffer of decoded message */
040 /* set pointer to TPSVCINFO data buffer */
041 transf = (FBFR *)transb->data;
042 /* must have valid account number */
043 if (((account_id = Fvall(transf, ACCOUNT_ID, 0)) < MINACCT) ||
044 (account_id > MAXACCT)) {
045 (void)Fchg(transf, STATLIN, 0, "Invalid account number", (FLDLEN)0);
046 tpreturn(TPFAIL, 0, transb->data, 0L, 0);
047 }
048 /* Set transaction level */
049 EXEC SQL set transaction read write;
050 /* Retrieve AMOUNT to be deleted */
051 EXEC SQL declare ccur cursor for
052 select BALANCE from ACCOUNT where ACCOUNT_ID = :account_id;
053 EXEC SQL open ccur;
054 EXEC SQL fetch ccur into :bal;
055 if (SQLCODE != SQL_OK) { /* nothing found */
056 (void)Fchg(transf, STATLIN, 0, getstr("account",SQLCODE), (FLDLEN)0);
057 EXEC SQL close ccur;
058 tpreturn(TPFAIL, 0, transb->data, 0L, 0);
059 }
060 /* Do final withdrawal */
061 /* make withdraw request buffer */
062 if ((reqfb = (FBFR *)tpalloc("FML",NULL,transb->len)) == (FBFR *)NULL) {
063 (void)userlog("tpalloc failed in close_acct\n");
064 (void)Fchg(transf, STATLIN, 0,
065 "Unable to allocate request buffer", (FLDLEN)0);
066 tpreturn(TPFAIL, 0, transb->data, 0L, 0);
067 }
068 reqlen = Fsizeof(reqfb);
069 (void)Finit(reqfb,reqlen);
070 /* put ID in request buffer */
071 (void)Fchg(reqfb,ACCOUNT_ID,0,(char *)&account_id, (FLDLEN)0);
072 /* put amount into request buffer */
073 (void)sprintf(amts,"%.2f",bal);
074 (void)Fchg(reqfb,SAMOUNT,0,amts, (FLDLEN)0);
075 /* increase the priority of this withdraw */
076 if (tpsprio(PRIORITY, 0L) == -1)
077 (void)userlog("Unable to increase priority of withdraw");
078 /* tpcall to withdraw service to remove remaining balance */
079 if (tpcall("WITHDRAWAL", (char *)reqfb, 0L, (char **)&reqfb,
080 (long *)&reqlen,TPSIGRSTRT) == -1) {
081 (void)Fchg(transf, STATLIN, 0,"Cannot make withdrawal", (FLDLEN)0);
082 tpfree((char *)reqfb);
083 tpreturn(TPFAIL, 0,transb->data, 0L, 0);
084 }
085 /* Delete account record */
086 EXEC SQL delete from ACCOUNT where current of ccur;
087 if (SQLCODE != SQL_OK) { /* Failure to delete */
088 (void)Fchg(transf, STATLIN, 0,"Cannot close account", (FLDLEN)0);
089 EXEC SQL close ccur;
090 tpfree((char *)reqfb);
091 tpreturn(TPFAIL, 0, transb->data, 0L, 0);
092 }
093 EXEC SQL close ccur;
094 /* prepare buffer for successful return */
095 (void)Fchg(transf, SBALANCE, 0, Fvals(reqfb,SAMOUNT,0), (FLDLEN)0);
096 (void)Fchg(transf, FORMNAM, 0, "CCLOSE", (FLDLEN)0);
097 (void)Fchg(transf, STATLIN, 0, " ", (FLDLEN)0);
098 tpfree((char *)reqfb);
099 tpreturn(TPSUCCESS, 0, transb->data, 0L, 0);
100 }
親トピック: エラーの管理