BEA Logo BEA Tuxedo Release 8.0

  BEA ホーム  |  イベント  |  ソリューション  |  パートナ  |  製品  |  サービス  |  ダウンロード  |  ディベロッパ・センタ  |  WebSUPPORT

 

   Tuxedo ホーム   |   C 言語を使用した BEA Tuxedo アプリケーションのプログラミング   |   先頭へ   |   前へ   |   次へ   |   目次

 


トランザクションの終了

グローバル・トランザクションを終了するには、tpcommit(3c) を呼び出して現在のトランザクションをコミットするか、または tpabort(3c) を呼び出して処理をアボートして、すべての操作をロールバックします。

注記 tpcall()tpacall()、または tpconnect() を呼び出すときに flags 引数に明示的に TPNOTRAN が設定されている場合、呼び出されたサービスによって実行される操作は、トランザクションに含まれません。つまり、このようなサービスによって実行される操作は、tpabort() 関数を呼び出したときにロールバックされません。

現在のトランザクションのコミット

tpcommit(3c) 関数は、現在のトランザクションをコミットします。tpcommit() 関数から正常に制御が戻ると、現在のトランザクションの結果としてリソースに加えられた変更は永続的なものとなります。

tpcommit() 関数の呼び出しには、次の文法を使用します。

int
tpcommit(long flags)

flags 引数は現在使用されていませんが、今後のリリースとの互換性を保つためにゼロに設定してください。

トランザクションをコミットするための条件

tpcommit() を正常に実行するには、次の 2 つの条件を満たしていることが必要です。

最初の条件を満たしていない場合、呼び出しは失敗し、プロトコル・エラーを示す TPEPROTOtperrno(5) に設定されます。2 番目または 3 番目の条件を満たしていない場合、呼び出しは失敗し、トランザクションがロールバックされたことを示す TPEABORTtperrno() に設定されます。トランザクションに未処理の応答があるときに tpcommit() がイニシエータによって呼び出されると、トランザクションはアボートされ、トランザクションに関連する応答記述子が無効になります。パーティシパントが tpcommit() または tpabort() を呼び出しても、トランザクションには影響しません。

サービス呼び出しで TPFAIL が返されるか、またはサービス・エラーが発生すると、トランザクションは「ロールバックのみ」の状態になります。「ロールバックのみ」のトランザクションに対して tpcommit() が呼び出されると、この関数はトランザクションを取り消し、-1 を返して tperrno(5)TPEABORT を設定します。既にタイムアウトになっているトランザクションに対して tpcommit() を呼び出した場合も同じ結果になり、tpcommit() は -1 を返して tperrno()TPEABORT が設定されます。トランザクション・エラーの詳細については、「エラーの管理」 を参照してください。

2 フェーズ・コミット・プロトコル

tpcommit() 関数が呼び出されると、2 フェーズ・コミット・プロトコルによる通信が開始されます。このプロトコルは、その名前が示すように、次の 2 段階の処理に分かれています。

  1. 参加する各リソース・マネージャがコミットの準備ができたことを示します。

  2. トランザクションのイニシエータが、参加する各リソース・マネージャにコミッ ト許可を与えます。

トランザクションのイニシエータが tpcommit() 関数を呼び出すと、コミット・シーケンスが開始されます。指定されたコーディネータ・グループ内の BEA Tuxedo TMS サーバ・プロセスは、コミット・プロトコルの最初のフェーズを実行する各パーティシパント・グループの TMS と通信を行います。次に、各グループの TMS は、そのグループのリソース・マネージャ (RM) に、トランザクション・マネージャ と RM 間の通信用に定義されている XA プロトコルを使用してコミットするように指示します。RM は、安定記憶域にコミット・シーケンスの前後のトランザクションの状態を書き込み、TMS に成功か失敗かを通知します。その後、TMS はトランザクション・コーディネータの TMS に応答を渡します。

トランザクション・コーディネータの TMS は、すべてのグループから成功の通知を受け取ると、トランザクションのコミット中であることをログに記録し、第 2 フェーズのコミット通知をすべてのパーティシパント・グループに送信します。その後、各グループの RM はトランザクションの更新を完了します。

トランザクション・コーディネータの TMS が、グループから第 1 フェーズのコミットの失敗の通知を受けた場合、またはグループからの応答の受信に失敗した場合、各 RM にロールバック通知を送信し、RM はすべてのトランザクション更新を以前の状態に戻します。これにより、tpcommit() は失敗し、tperrno(5)TPEABORT が設定されます。

コミットの成功条件の選択

1 つのトランザクションに複数のグループが関係している場合、tpcommit() が正常に制御を戻すための条件として、次のいずれかを指定できます。

この 2 つの条件のいずれかを指定するには、コンフィギュレーション・ファイルの RESOURCESCMTRET パラメータに、次のいずれかの値を設定します。

デフォルトでは、CMTRETCOMPLETE に設定されます。

後でコンフィグレーション・ファイルの設定値を変更する場合は、flags 引数に TP_CMT_LOGGED または TP_CMT_COMPLETE を設定して、tpscmt() を呼び出します。

コミット条件での妥協点

ほとんどの場合、グローバル・トランザクションのすべてのパーティシパントが第 1 フェーズの正常終了を記録した場合、第 2 フェーズも正常終了します。CMTRETLOGGED を設定すると、tpcommit() の呼び出しから制御が多少早く戻るようになります。ただし、パーティシパントが、コミットの決定と矛盾する方法で、トランザクションの担当部分をヒューリスティックに終了する危険性があります。

このようなリスクを負うべきかどうかの選択は、アプリケーションの性質に左右されます。たとえば、財務アプリケーションなど正確さが要求されるアプリケーションでは、すべてのパーティシパントが 2 フェーズ・コミットを完了するまでは、制御を戻さないようにします。時間的な条件を重視するアプリケーションでは、正確さを犠牲にしても実行速度を上げます。

現在のトランザクションのアボート

tpabort(3c) 関数を使用すると、異常な状態を通知して、明示的にトランザクションをアボートできます。この関数は、トランザクションの応答に未処理のものがあると、その呼び出し記述子を無効にします。その場合、トランザクションで行われた変更はリソースには適用されません。tpabort() 関数の呼び出しには、次の文法を使用します。

int
tpabort(long flags)

flags 引数は現在使用されていませんが、今後のリリースとの互換性を保つためにゼロに設定してください。

例: 会話モードによるトランザクションのコミット

次の図は、グローバル・トランザクションを行う階層構造の会話型接続を示しています。

トランザクション・モードにおける接続階層構造


 

接続階層構造は、次の処理が行われることで構築されます。

  1. クライアント (プロセス A) は、tpbegin()tpconnect() を呼び出して、トラ ンザクション・モードで接続を開始します。

  2. クライアントは、実行する下位サービスを呼び出します。

  3. 各下位サービスは、処理が完了すると、処理が成功したか失敗したか (TPEV_SVCSUCC または TPEV_SVCFAIL) を示す応答を階層構造を通じてトランザ クションを開始したプロセスに送信します。この例では、トランザクションを開 始したプロセスはクライアント (プロセス A) です。下位サービスは、応答の送信 が終了すると、つまり未処理の応答がなくなると、tpreturn() を呼び出しま す。

  4. クライアント (プロセス A) は、すべての下位サービスが正常終了したかどうかを確認します。

例: パーティシパントのエラーの確認

次のコード例では、クライアントは REPORT サービスへの同期呼び出し (18 行目) を行います。次に、通信呼び出しで返される可能性があるエラーを調べて (19 〜 34 行目) 、パーティシパントの失敗を確認します。

パーティシバントの成功/失敗の確認

001    #include <stdio.h>
002 #include "atmi.h"
003
004 main()
005 {
006 char *sbuf, *rbuf;
007 long slen, rlen;
008 if (tpinit((TPINIT *) NULL) == -1)
009 error message, exit program;
010 if (tpbegin(30, 0) == -1)
011 error message, tpterm, exit program;
012 if ((sbuf=tpalloc("STRING", NULL, 100)) == NULL)
013 error message, tpabort, tpterm, exit program;
014 if ((rbuf=tpalloc("STRING", NULL, 2000)) == NULL)
015 error message, tpfree sbuf, tpabort, tpterm, exit program;
016 (void)strcpy(sbuf, "REPORT=accrcv DBNAME=accounts");
017 slen=strlen(sbuf);
018 if (tpcall("REPORT", sbuf, slen, &rbuf, &rlen, 0) == -1) {
019 switch(tperrno) {
020 case TPESVCERR:
021 fprintf(stderr,
022 "REPORT service's tpreturn encountered problems\n");
023 break;
024 case TPESVCFAIL:
025 fprintf(stderr,
026 "REPORT service TPFAILED with return code of %d\n", tpurcode);
027 break;
028 case TPEOTYPE:
029 fprintf(stderr,
030 "REPORT service's reply is not of any known data type\n");
031 break;
032 default:
033 fprintf(stderr,
034 "REPORT service failed with error %d\n", tperrno);
035 break;
036 }
037 if (tpabort(0) == -1){
038 check for errors;
039 }
040 }
041 else
042 if (tpcommit(0) == -1)
043 fprintf(stderr, "Transaction failed at commit time\n");
044 tpfree(rbuf);
045 tpfree(sbuf);
046 tpterm();
047 exit(0);
048 }

 

先頭へ戻る 前のトピックへ 次のトピックへ