|
|
C 言語アプリケーション・トランザクション・モニタ・インターフェイスについて
機能説明
アプリケーション・トランザクション・モニタ・インターフェイス(ATMI:Application-to-Transaction Monitor Interface)は、アプリケーションとトランザクション処理システムとの間に介在し、ATMI インターフェイスと呼ばれています。このインターフェイスは、リソースのオープンとクローズ、トランザクションの管理、型付きバッファの管理、要求/応答型サービス呼び出しや会話型サービス呼び出しの起動などを行う関数呼び出しを提供します。
コミュニケーション・パラダイム
ATMI リファレンス・ページに記述されている関数呼び出しには、特定のコミュニケーション・モデルがあります。このモデルは、クライアント・プロセスとサーバ・プロセスが要求および応答の各メッセージを使用して如何にコミュニケートできるかという観点から表現されています。
コミュニケーションの基本的パラダイムとして、要求/応答型と会話型の 2 つがあります。要求/応答型サービスは、サービス要求とそれに関わるデータによって呼び出されます。要求/応答型サービスは、要求を 1 つだけ受け取ることができ (該当サービス・ルーチンに入った時点で)、かつ応答も 1 つだけ送信することができます (該当サービス・ルーチンから戻った時点で)。一方、会話型サービスは接続要求によって呼び出されます。このとき、オープンされた接続を参照する手段が必要です (すなわち、以後の接続ルーチンを呼び出す際に使用される記述子)。接続が確立され、サービス・ルーチンが呼び出されると、以後、接続プログラムあるいは会話型サービスは、その接続が解除されるまで、アプリケーションによって定義されたようにデータの送受信を行えるようになります。
なお、プロセスは要求/応答型と会話型によるコミュニケーションのいずれをも行うことができますが、両方のサービス要求を受け付けることはできません。以下の節では、これら 2 種類のコミュニケーション・パラダイムについてその概要を説明します。
注記 BEA Tuxedo のマニュアルでは、さまざまな場所でスレッドについて説明しています。マルチスレッドのアプリケーションの説明で「スレッド」と記載されている場合は、文字どおりのスレッドを意味します。ただし、シングルスレッドとマルチスレッドの両方のアプリケーションに関するトピックで「スレッド」という言葉が使用される場合があります。このような場合にシングルスレッド・アプリケーションを実行していれば、「スレッド」はプロセス全体を指しているものと考えてください。
BEA Tuxedo ATMI システムのクライアント/サーバ用要求/応答型パラダイム
要求/応答型のコミュニケーションの場合、クライアントは要求を送り、応答を受け取ることができる 1 つのプロセスと定義されています。定義によれば、クライアントは要求を受け取ったり、応答を送ったりすることはできません。その代わり、クライアントはいくつでも要求を送ることができ、またそれと同時に応答を待ったり、あるいは適宜ある一定数の応答を受け取ったりすることができます。場合によっては、クライアントは応答を必要としない要求を送ることもできます。tpinit() と tpterm() を使用すれば、クライアントは BEA Tuxedo ATMI システム・アプリケーションと結合および分離することができます。
一方、要求/応答型サーバは一度に 1 つのサービス要求を受け取り、その要求に対して 1 つの応答を返すことができるプロセスと定義されています。ただし、サーバがマルチスレッドであれば、一度に複数の要求を受け取り、一度に複数の応答を返すことができます。サーバは特定の要求を処理しながら、一方で要求/応答型要求あるいは会話型要求を出し、それらの応答を受け取ることにより、クライアントのように働くこともできます。サーバはこうした能力の故に、リクエスタと呼ばれることもあります。ただし、クライアント・プロセスとサーバ・プロセスはどちらもリクエスタになることができます (実際、クライアントはリクエスタ以外の何物でもありません)。
要求/応答型サーバは別の要求/応答型サーバに要求を送る (転送する) ことができます。この場合、最初のサーバは受け取った要求を別のサーバに渡すだけで、応答を受け取ることは期待しません。この連鎖の中の最後サーバがその要求に対する応答をもとのリクエスタに送ります。この転送ルーチンの利用によって、もとのリクエスタは最終的にその応答を受け取ることができるのです。
サーバとサービス・ルーチンの利用から、BEA Tuxedo ATMI システム・アプリケーションの作成に構造化手法をとることが可能になります。サーバ側では、アプリケーション作成者は、要求の受信や応答の送信といったコミュニケーションの詳細ではなく、サービスによって実行する事柄に関する作業に専念すればよいのです。コミュニケーション上の詳細の多くは BEA Tuxedo ATMI システムの main が処理するため、サービス・ルーチンを作成するときにはある一定の規則に従う必要があります。サーバは、そのサービス・ルーチンを終了する時点で、tpreturn() を使用して応答を送ったり、あるいは tpforward() を使用して要求を転送したりできます。サービスはその他の作業を行ったり、この時点以後別のプロセスとコミニュニケートすることは許されません。そのため、サーバが実行するサービスは、要求が受け取られたときに開始され、応答が送信あるいは要求が転送された時点で終了します。
要求メッセージと応答メッセージとの間には、本質的に異なる点があります。すなわち、要求にはそれが送信される以前には関連するコンテキストはありませんが、応答にはあるという点です。たとえば、ある要求を送る際に、呼び出し元はアドレッシング情報を与えなければなりませんが、応答は常にその要求を出したプロセスに返されます。つまり、応答の場合には、要求が出されるときに与えられたアドレッシング情報が維持されていて、応答の送信側はそのあて先になんら手を加えることはできません。この両者の相違点については、TPCALL(3cbl) のルーチンのパラメータと説明で明らかにされています。
要求メッセージはその送信時に特定の優先順位が付与されます。この優先順位にしたがって、要求はキューから取り出されます。つまり、サーバはキューの中で最も優先順位の高い要求から順に取り出すのです。ただし、要求がいつまでもキューの中に残されてしまうのを防ぐために、優先順位に関係なく、最も長くキューに入っている要求が一定間隔で取り出されます。デフォルト設定では、要求の優先順位はその要求が送られるサービス名に対応させて付けられます。サービス名にはシステムのコンフィギュレーション時に優先順位を与えることができます (UBBCONFIG(5) 参照)。特に定義されていない場合には、デフォルトの優先順位が使用されます。この優先順位は、tpcall(3c) に説明のあるルーチン (tpsprio()) を使用して実行時に設定することができます。呼び出し元はこの方法により、メッセージ送信時にコンフィギュレーションまたはデフォルトの優先順位を変更できます。
BEA Tuxedo ATMI システムのクライアント/サーバ用会話型パラダイム
会話型のコミュニケーションの場合、クライアントは、会話接続を行うことはできるが、接続要求を受け付けることはできないプログラムと定義されています。
一方、会話型サーバは、接続要求を受け取ることができるプログラムです。接続が確立され、サービス・ルーチンが呼び出されると、以後、接続プログラムあるいは会話型サービスは、その接続が解除されるまで、アプリケーションによって定義されたようにデータの送受信を行えるようになります。会話は半二重方式で行われます。つまり、接続の一方の側が制御権をもってデータを送信し、他方の側は制御権を渡されるまではデータを送信できません。シングルスレッド・サーバでは、接続中のサーバは「予約状態」になり、他のプログラムがそのサーバに接続することはできません。しかしマルチスレッド・サーバに接続しても、そのサーバが 1 プロセスの専用サーバとして予約状態になることはなく、複数のクライアントのスレッドから要求を受け取ることができます。
要求/応答型サーバの場合と同様、会話型サーバは他の要求を出したり、他のサーバとの接続を行うことによりリクエスタとして機能できます。一方、要求/応答型サーバと異なり、会話サーバは要求を別のサーバに転送することはできません。このため、会話サーバによって実行される会話サービスは、要求を受け取った時点で開始され、tpreturn() を介して最終的な応答が送信された時点で終了します。
接続が確立されると、その接続記述子から、参加プロセス (パーティシパント) に関するアドレッシング情報を得るために必要なコンテキストが分かります。メッセージは、アプリケーション側の規定に従って送受信することができます。要求メッセージ応答メッセージとの間には本質的な相違はなく、またメッセージの優先順位に関する規定もありません。
メッセージの配信
会話モードの場合でも、要求/応答モードの場合でも、メッセージの送受信とは、アプリケーションの 2 つのユニット間のコミュニケーションを意味します。ほとんどの場合、メッセージによって応答または少なくとも承認が送られることになります。ですから、メッセージが確実に受信されたことが確認できます。しかし、メッセージ (システムが生成したメッセージやアプリケーションが生成したメッセージ) の中には、応答や承認を得ることができないものもあります。たとえば、システムは tpnotify() を TPACK() フラグなしで使用して任意通知型メッセージを送信でき、アプリケーションは tpacall() を TPNOREPLY() フラグ付きで使用して、メッセージを送信を行うことができます。受信プログラムのメッセージ・キューがいっぱいになった場合は、メッセージは失われます。
送信側と受信側が別のマシンにある場合、コミュニケーションは、ネットワークでメッセージを送受信する BRIDGE プロセス間で行われます。回線異常により、配信失敗の可能性が生じます。このような状況によって、イベントの発生や ULOG メッセージの書き込みを行っても、このイベントや ULOG メッセージと失われたメッセージを結びつけることは容易ではありません。
BEA Tuxedo ATMI システムの目的は広域ネットワークで大量のメッセージを処理することなので、前述のような小さな配信異常を検知して調整できるようにはプログラムされていません。このような理由から、すべてのメッセージを確実に配信できるという保証はありません。
メッセージのシーケンス (順序付け)
tpsend() および tprecv() を使用してメッセージを交換する会話型モデルの場合、メッセージ・ヘッダにシーケンス番号を付加し、送信された順番に受信します。サーバまたはクライアントが順序の誤ったメッセージを受け取ると会話が停止して、進行中のすべてのトランザクションはロールバックし、メッセージ LIBTUX 1572「間違った会話型シーケンス番号」がログに記録されます。
要求/応答モードでは、システムがメッセージを順序付けることはありません。アプリケーション・ロジックが順番を付けた場合、アプリケーションがこのシーケンスを監視し制御する責任があります。BRIDGE プロセス用の複数ネットワーク・アドレスをサポートすることで実現する並列メッセージ送信を行うことにより、メッセージが送信順に受信されない可能性が高まります。関連するアプリケーションによって、各 BRIDGE プロセスで使用する単一ネットワークアドレスを指定することができ、またメッセージにシーケンス番号を付加したり、定期的な承認を要求したりすることもできます。
キュー・メッセージ・モデル
BEA Tuxedo ATMI システムのキュー・メッセージ・モデルは、要求メッセージの完了を待たず、そのメッセージが後で処理されるようにキューに登録し、またオプションとしてキューに入れられた応答メッセージを介して応答が得られるようにします。メッセージをキューに登録したり応答をキューから取り出すための ATMI 関数は、tpenqueue() と tpdequeue() です。これらの関数は、BEA Tuxedo ATMI システムのアプリケーション・プロセスの全ての型:クライアント、サーバ、会話型のいずれのプロセスからも呼び出せます。キューに登録するアプリケーションもキューから取り出すアプリケーションも、サーバまたはクライアントとして指定されていない場合、関数 tpenqueue() と tpdequeue() をピア・ツー・ピア通信に使用することができます。
キュー・メッセージ機能は、XA 準拠のリソース・マネージャで提供されます。永続的なメッセージはトランザクション内でキューへの登録および取り出しが行われ、一度に処理されます。
ATMI トランザクション
BEA Tuxedo ATMI システムは、トランザクションの定義および管理について、相互に排他的な 2 つの関数をサポートしています。BEA Tuxedo システムの ATMI トランザクション境界関数 (名前の先頭が tp) と、X/Open の TX インターフェイス関数 (名前の先頭が tx_) です。X/Open では TX インターフェイスのベースとして ATMI のトランザクション境界関数が使用されるので、TX インターフェイスの構文およびセマンティクスは、ATMI とほとんど同じです。この項では、ATMI のトランザクション概念について概要を述べます。次の項では、TX インターフェイスについて補足説明します。
BEA Tuxedo ATMI システムにおけるトランザクションは、全体としてある結果を導く、あるいは何も結果を示さない 1 つの論理的な作業単位を定義するときに使用します。トランザクションにより、多くのプロセスによって (そして、おそらく様々な場所で) なされる作業を 1 つの作業単位として扱うことができます。トランザクションの開始者は TPBEGIN(3cbl) および TPCOMMIT(3cbl) または TPABORT(3cbl) を使用してトランザクション内での操作内容を記述します。
イニシエータはまた、tpsuspend() を呼び出して現在のトランザクションでの作業を中断することもできます。他のプロセスが tpresume() を呼び出して、中断されているトランザクションのイニシエータの役割を引き継ぐこともできます。トランザクションのイニシエータとして、プロセスはtpsuspend()、tpcommit() または tpabort() のいずれかを呼び出す必要があります。従って、あるプロセスがトランザクションを終了し、別のプロセスがトランザクションを開始することができます。
サービスを呼び出すプロセスがトランザクション・モードにあると、呼び出されたサービス・ルーチンも同じトランザクションのためにトランザクション・モードに入ります。このプロセスがトランザクション・モードでない場合、サービスがトランザクション・モードで呼び出されるかどうかは、コンフィギュレーション・ファイルにおいて該当サービスにどのようなオプションが指定されているかによって決まります。トランザクション・モードで呼び出されないサービスは、それが呼び出された時点から終了時点までの間に複数のトランザクションを定義できます。一方、トランザクション・モードで呼び出されたサービス・ルーチンは、1 つのトランザクションにのみ関与し、終了するまでそのトランザクションでの作業を続けます。なお、接続をトランザクション・モードにアップグレードすることはできません。会話接続中に tpbegin() が呼び出されると、会話状態はそのトランザクションの外側で維持されます (tpconnect() が TPNOTRAN() フラグ付きで呼び出された場合と同様)。
別のプロセスによって起動されたトランザクションに加わるサービスを、パーティシパントと呼びます。トランザクションは常に、1 つのイニシエータをもち、かついくつかのパーティシパントをもつことができます。同じトランザクションでの作業を行うためにサービスを 2 回以上呼び出すことができます。tpcommit() あるいは tpabort() を呼び出すことができるのは、トランザクションのイニシエータだけです (つまり、tpbegin() または tpresume() のいずれかを呼び出すプロセス)。パーティシパントは、tpreturn() あるいは tpforward() を使用することによりトランザクションの結果に影響を与えます。これらの 2 つの呼び出しはそれぞれ、サービス・ルーチンの終わり、およびそのルーチンがトランザクションの中でそれが担当する部分を終了したことを示すものです。
TX トランザクション
TX インターフェイスによって定義されるトランザクションは、ATMI 関数によって定義されるトランザクションと実質的に同じです。アプリケーション開発者は、クライアントとサービスのルーチンを作成する場合、どちらの関数も使用できますが、同一プロセス内に異なる関数を混在させることはできません。つまり、1 つのプロセスで tpbegin() を呼び出した後に tx_commit() を呼び出すことはできません。
TX インターフェイスには、移植性の高い方法でリソース・マネージャのオープンとクローズを行う 2 つの呼び出し tx_open() および tx_close() があります。トランザクションは、tx_begin() で開始され、tx_commit() または tx_rollback() のいずれかで完了します。tx_info() は、トランザクション情報を取り出す際に使用されます。また、トランザクションにオプションを設定する 3 つの呼び出し、tx_set_commit_return()、tx_set_transaction_control()、およびtx_set_transaction_timeout() があります。TX インターフェイスには、ATMIの tpsuspend() と tpresume() に相当するものはありません。
TX インターフェイスには、ATMI トランザクションについて定義されているセマンティクスおよび規則の他にも、ここで説明しておくべきセマンティクスがいくつかあります。TX インターフェイスを使用するサービス・ルーチン開発者は、tpsvrinit() を呼び出す独自の tx_open() ルーチンを使用する必要があります。BEA Tuxedo ATMI システムが提供するデフォルトの tpserverinit() は、tpopen() を呼び出します。tpsvrdone() についても同じことがあてはまります。TX インターフェイスを使用している場合は、サービス・ルーチン開発者は、tx_close() を呼び出す独自の tpsvrdone() を使用しなければなりません。
次に、TX インターフェイスには、ATMI にはない別のセマンティクスが 2 つあります。それは、連鎖および非連鎖トランザクションと、トランザクション特性です。
連鎖および非連鎖トランザクション
TX インターフェイスは、トランザクション実行の連鎖モードおよび非連鎖モードをサポートしています。デフォルトでは、クライアント・ルーチンおよびサービス・ルーチンは、非連鎖モードで実行されます。この場合、アクティブなトランザクションが完了した際、新しいトランザクションは tx_begin() が呼び出されるまで開始されません。
連鎖モードでは、新しいトランザクションは、現在のトランザクションが完了すると、暗黙に開始されます。つまり、tx_commit() または tx_rollback() が呼び出されると、BEA Tuxedo ATMI システムは、現在のトランザクションの完了を調整し、制御を呼び出し元に返す前に新しいトランザクションを開始します。(異常終了の条件によっては、新しいトランザクションを開始できない場合もあります)。
クライアント・ルーチンおよびサービス・ルーチンは、tx_set_transaction_control() を呼び出すことによって連鎖モードのオンとオフを切り替えます。連鎖モードと非連鎖モードの間の遷移により、その次の tx_commit() 呼び出しまたは tx_rollback() 呼び出しの動作が変わります。tx_set_transaction_control() の呼び出しでは、呼び出し元のトランザクション・モードのオンとオフの切り替えは行いません。
tx_close() は、呼び出し元がトランザクション・モードにあるときには呼び出すことができないため、連鎖モードで実行中の呼び出し元が tx_close() を呼び出すには、非連鎖モードに切り替えて、現在のトランザクションを完了してから呼び出さなければなりません。
トランザクション特性
クライアント・ルーチンまたはサービス・ルーチンは、tx_info() を呼び出すことによって、そのルーチンのトランザクション特性の現在の値を取得したり、そのルーチンがトランザクション・モードで実行中であるかどうかを判別したりすることができます。
アプリケーション・プログラムの状態には、いくつかのトランザクション特性があります。呼び出し元は、tx_set_*() 関数の呼び出しによってこれらの特性を指定します。クライアント・ルーチンまたはサービス・ルーチンが特性の値を設定している場合は、異なる値を呼び出し元が指定するまでは、その値が有効のままです。呼び出し元が tx_info() を使用して特性の値を取得しても、これによって値が変更されることはありません。
エラー処理
多くの場合、ATMI 機能には 1 つまたは複数のエラー・リターンがあります。エラーの条件は、エラーの他には考えられない戻り値で示されます。この値は通常、エラー時で -1、間違ったフィールド識別子 (BADFLDID) またはアドレスの場合 0 となります。エラー・タイプは外部整数 tperrno() でも参照することができます。正常な呼び出しによって tperrno() がリセットされることはないので、エラーを検出した後にしか呼び出しのテストを行ってはいけません。
tpstrerror() 関数は標準エラー出力へのメッセージを生成します。この関数では 1 つの引数、つまり整数 (tperrno() にセットされている) を必要とし、LIBTUX_CAT のエラー・メッセージ・テキストへのポインタを返します。このポインタは userlog() の引数として使用できます。
現行スレッドで最後の BEA Tuxedo ATMI システム呼び出し時にエラーが発生した場合、エラーの詳細をさらに調べるには手順が 3 つあり、その第一段階として tperrordetail() を使用することができます。tperrordetail() は整数を返しますが、この整数は、エラーメッセージが含まれる文字列へのポインタを取り出す、tpstrerrordetail() の引数として使用します。ポインタは userlog または fprintf() の引数として使用できます。
エラーコードのうち、ATMI 関数で生成できるものについては、ATMI のマニュアル・ページで説明しています。F_error() と F_error32() 関数は、FML エラーの標準エラー出力にメッセージを出力します。この関数は、パラメータを 1 つ (文字列) 取り、コロンと空白を付加してその引数文字列を出力します。次に、エラー・メッセージとその後に続く復帰改行文字を出力します。表示されたエラー・メッセージは Ferror() または Ferror32() で定義したエラー番号に対応しています。これらはエラーが発生した時点で設定されます。
エラー・メッセージのテキストをメッセージ・カタログから取り出す時、Fstrerror() およびこれに相当する Fstrerror32() を使用することができます。これらによって userlog の引数として使用できるポインタを返します。
エラーコードのうち、FML 機能で生成できるものについては、マニュアルの FML の項目で説明しています。
タイムアウト
BEA Tuxedo ATMI システムには 3 種類のタイムアウトがあります。1 つはトランザクションの開始から終了までの期間に関連するもの、2 つめはブロッキング・コールで呼び出し元が制御権を再度入手するまでブロック状態を維持する最大時間に関連するものです。3 つめはサービスのタイムアウトです。これは呼び出しの秒数がコンフィギュレーション・ファイルの SERVICES セクションにおける SVCTIMEOUT パラメータで指定された秒数を越えた時に発生します。
最初のタイムアウトは、tpbegin() を使用してトランザクションを開始するときに指定します(詳細については、tpbegin(3c) を参照)。 2 つ目のタイムアウトは、tpcall(3c) に定義されている BEA Tuxedo ATMI システムのコミュニケーション・ルーチンを使用する際に発生することがあります。これらのルーチンの呼び出し元は一般に、まだ届いていない応答を待っている間はブロック状態になります。これらの呼び出し元はデータの送信を行うこともブロックされることがあります (たとえば、要求キューがいっぱいの場合など)。呼び出し元がブロック状態になる最大時間は、BEA Tuxedo ATMI システムのコンフィギュレーション・ファイルに記述されているパラメータによって決まります(詳細については、UBBCONFIG(5) の BLOCKTIME パラメータの項を参照してください)。
ブロッキング・タイムアウトは呼び出し者がトランザクション・モードにないときにデフォルトの設定によって実行されます。クライアントあるいはサーバがトランザクション・モードにあると、そのトランザクションが開始したときに指定されたタイムアウト値が働き、UBBCONFIG ファイルに指定されているブロッキング・タイムアウト値の影響は受けません。
トランザクション・タイムアウトが発生すると、トランザクション・モードで行われた非同期の要求に対する応答は失効状態になることがあります。つまり、あるプロセスが、トランザクション・モードで送信された要求に対する特定の非同期応答の到着を待っているときに、トランザクション・タイムアウトが発生すると、その応答の記述子が無効になります。同様に、トランザクション・タイムアウトが発生すると、そのトランザクションに関連付けられている記述子に対してイベントが生成され、その記述子は無効になります。一方、ブロッキング・タイムアウトが発生した場合、該当する記述子は無効にならず、応答を待機しているプロセスはその応答を待機するための呼び出しを再度出すことができます。
サービス・タイムアウト機構によって、未知の、または予期しないシステム・エラーが原因でフリーズする可能性のあるプロセスについて、システムが強制終了を行うことができます。要求/応答サービス時にサービス・タイムアウトが発生すると、BEA Tuxedo ATMI システムによって、フリーズしたサービスを実行中のサーバ・プロセスが強制終了され、エラーコード TPESVCERR が戻ります。サービス・タイムアウトが会話型サービスで発生した場合は、TP_EVSVCERR イベントが返ります。
トランザクションがタイムアウトになった場合、そのトランザクションがアボートされる前の接続のうち、TPNOREPLY、TPNOTRAN、および TPNOBLOCK 付きの tpacall() への呼び出しのみが有効です。
リリース 6.4 から、TPESVCERR エラー・コードに関する詳細が追加されました。タイムアウトのしきい値を超えたためにサービスが失敗した場合、イベント .SysServiceTimeout がポストされます。
動的サービス宣言
デフォルトの設定では、サーバのサービスは、それがブートされるときに宣言され、シャットダウンするときに宣言が解除されます。サーバは、それが提供するサービス・セットに対する制御を実行時に必要とする場合、tpadvertise() および tpunadvertise() を使用します。これらのルーチンは、該当サーバが複数サーバ、単一キュー (MSSQ) セットに属していないかぎり、呼び出し元サーバが提供するサービスだけに影響します。MSSQ セットのサーバはすべて同じサービス・セットを提供しなければならないため、これらのルーチンもまた呼び出し元の MSSQ セットを共用するすべてのサーバの宣言に影響します。
バッファ管理
プロセスはその生成当初、バッファをもちません。メッセージの送信前に tpalloc() を使用してバッファを割り当てなければなりません。送信元のデータはこの後、割り当てられたバッファに一旦入れた後、送信することができます。このバッファは特有の構造をもっています。この構造は、tpalloc() 関数に type 引数を付けて指定します。ある種の構造にはさらに分類が必要になるので、サブタイプも与えることができるようになっています (たとえば、特定タイプの C 構造体など)。
メッセージを受け取る際には、アプリケーション・データを受け取ることができるバッファが必要です。このバッファは tpalloc() によって作成されたものでなければなりません。なお、BEA Tuxedo ATMI システムのサーバはその main においてバッファを割り当てますが、このバッファのアドレスはサービス呼び出し時に要求/応答型サービスまたは会話型サービスに渡されます(このバッファの扱い方の詳細については、tpservice(3c) を参照)。
メッセージの受信に使用するバッファは、送信に使用するバッファとは扱い方が若干異なります。バッファの大きさとアドレスはメッセージの受信にともなって変わります。これは、システムが内部で受信コールに渡されたバッファを、バッファを処理するのに使用する内部バッファと交換するからです。バッファ・サイズは、受信にともない増加することも減少することもあります。増加するか減少するかは、すべて送信側から送られたデータの量と、受信側が送信側からデータを受け取るために必要な内部データのフローによって決まります。バッファ・サイズに影響を与える要素は数多くあり、圧縮、異なるマシン・タイプからのメッセージの受信、使用されるバッファ・タイプの postrecv() 関数のアクションなどが挙げられます (buffer(3c) を参照)。ワークステーション・クライアントのバッファ・サイズは、通常ネイティブ・クライアントのバッファ・サイズとは異なります。
受信バッファは、メッセージを受信する実際の容器というよりプレイス・ホルダであると考えたほうがよいでしょう。システムは、渡したバッファ・サイズをヒントとして使用することもあるので、バッファを予想される応答を入れられるだけの大きさにすることには意味があります。
送信側では、バッファ・タイプは割り当てられた容量まで満たされないこともあります (例えば、FML や STRING バッファは送信に使われただけの大きさです)。ひとつの整数フィールドを含む 100K の FML32 バッファは、その整数だけを含むより小さいバッファとして送られます。
これは、受信者が送信者の割り当てたバッファ・サイズより小さく、送信されたデータのサイズより大きいバッファを受け取るということです。たとえば、10K バイトの STRING バッファが割り当てられ、文字列 "HELLO" がその中にコピーされた場合は、6 バイトのみが送られますが、受信者は 1K から 4K バイトのバッファを受け取ることになります(他の要素によりこれより大きかったり小さかったりします)。BEA Tuxedo ATMI システムは、受信メッセージがすべての送信されたデータを含んでいることは保証しますが、すべてのフリー・スペースまで保証するわけではありません。
応答を受信するプロセスは、バッファ・サイズの変更を知らせ (tptypes() を使用します)、必要な場合は割り当てをやり直します。受信者のバッファ・サイズを変えるすべての BEA Tuxedo ATMI 関数は、バッファ内のデータの量を返すので、応答を受信するたびにバッファ・サイズを確認するのが標準になるでしょう。
メッセージの送受信には同じデータ・バッファを使用することができます。また、それぞれのメッセージに対して別々のデータ・バッファを割り当てることも可能です。通常は、呼び出しプロセスが tpfree() を使用してそのバッファを解放します。ただし、ごく限られたケースでは、BEA Tuxedo ATMI システムが呼び出し元のバッファを解放します。バッファの使い方の詳細については、tpfree() などの通信関数の説明を参照してください。
バッファ・タイプ・スイッチ
tmtype_sw_t 構造体は、新しいバッファ・タイプをプロセスのバッファ・タイプ・スイッチ tm_typesw() に追加するために必要とされる記述です。スイッチ・エレメントは typesw(5) に定義されています。このエントリに使用される関数名は、BEA Tuxedo ATMI システムまたは独自のバッファ・タイプを作成するアプリケーションによって定義される実際の関数名のテンプレートとなります。これらの関数名は、簡単にスイッチ・エレメントにマップできます。テンプレート名を作成するには、関数ポインタのエレメント名の最初に _tm を追加します。たとえば、エレメント initbuf のテンプレート名は、_tminitbuf になります。
エレメント type は NULL 以外とし、最大 8 文字とします。この要素がスイッチ内で一意でない場合、subtype() は NULL 以外でなければなりません。
エレメント subtype() には NULL、最大 16 文字の文字列、または * (ワイルドカード文字) のいずれかを使用できます。type() と subtype() の組み合わせは、スイッチ内で一意に要素を指定するものでなければなりません。
あるタイプに複数のサブタイプがあってもかまいまいせん。すべてのサブタイプをあるタイプに対して同じように扱う場合、ワイルドカード文字 "*" を使用できます。なお、サブタイプを区別する必要がある場合には、関数 tptypes() を使用して、バッファのタイプとサブタイプを弁別することができます。ある特定のタイプ内で一定のサブタイプのサブセットを個別に扱う必要があり、残りを同様に扱う場合には、特定の値でまとめるサブタイプは、ワイルドカードで指定する前にスイッチ内に指定しておく必要があります。このため、まずスイッチ内のタイプとサブタイプの検索が上から下の方向に行われ、ワイルドカードによるサブタイプのエントリは、残りの一致するタイプを受け付けることになります。
要素 dfltsize() は、バッファの割り当てまたは再割り当てを行うときに使用します。tpalloc() と tprealloc() の実行では、dfltsize() の値か、または tpalloc() および tprealloc() 関数のサイズ・パラメータ値の、どちらか大きい方の値を使用して、バッファの作成または再割り当てが行われます。固定サイズの C 構造体などの場合、バッファ・サイズはその構造体と同じにするべきです。dfltsize() をこの値に設定すると、呼び出し元はバッファが渡されるルーチンに対してそのバッファの長を指定する必要はなくなります。dfltsize() は 0 あるいはそれ以下にすることができます。ただし、tpalloc() や tprealloc() を呼び出して、その size パラメータも 0 もしくはそれ以下であると、このルーチンは異常終了します。dfltsize() は 0 よりも大きい値に設定することをお勧めします。
BEA Tuxedo ATMI システムには、5 つの基本バッファ・タイプがあります。
上記のバッファ・タイプの中の 2 つには、同等のタイプがあります。X_OCTET は CARRAY と同じであり、X_C_TYPE および X_COMMON は VIEW と同じです。X_C_TYPE は、VIEW がサポートするすべての要素をサポートします。これに対し、X_COMMON は、long、short、character のみをサポートします。X_COMMON は、C と COBOL の両方のプログラムがやりとりする際に、使用してください。
アプリケーションで独自のバッファ・タイプを使用する場合には、tm_types 配列 にそのインスタンスを追加します。バッファ・タイプを追加したり削除したりする場合は、配列の終わりにヌル・エントリをそのまま残しておくようにしてください。ただし、NULL 名をもつバッファ・タイプを使用することはできません。buildserver() または buildclient() コマンド行に、-f オプションを用いてソースまたはオブジェクト・ファイルを明示的に指定することにより、アプリケーション・クライアントまたはサーバが、新しいバッファ・タイプ・スイッチにリンクされます。
任意通知
上記のように定義されたクライアント/サーバ間でのやりとりの境界外からメッセージをアプリケーション・クライアントに送る方法は2通りあります。第 1 の方法は、tpbroadcast() によって実現されるブロードキャスト機構です。この関数により、アプリケーション・クライアント、サーバおよび管理者は割り当てられた名前に基づいて選択されるクライアントに型付きバッファ・メッセージをブロードキャストすることができます。クライアントに割り当てられる名前は、一部はアプリケーションにより TPINIT 型付きバッファに tpinit() 実行時に渡される情報ごとに、また一部はクライアントがアプリケーションのアクセスに使用するプロセッサに基づいてシステムにより決められます。
もう 1 つの方法は、以前のあるいは現在のサービス要求から識別される特定クライアントによる通知方法です。各サービス要求には、そのサービス要求を出したクライアントを特定する一意のクライアント識別子が含まれています。サービス・ルーチン内で tpcall() や tpforward() が呼び出されても、そのサービス要求の連鎖に対応する元のクライアントは変更されません。クライアント識別子は保存しておき、アプリケーション・サービス間で受け渡すことができます。この方法で特定されたクライアントに対する通知は、関数 tpnotify() を使用して行います。
プロセスごとのシングルコンテキストとマルチ・コンテキスト
BEA Tuxedo ATMI システムでは、クライアント・プログラムはプロセスごとに 1 つまたは複数のアプリケーションとの関連を作成することができます。TPINIT 構造体のフラグ・フィールドに TPMULTICONTEXTS パラメータを指定して tpinit() が呼び出された場合は、複数のクライアント・コンテキストを使用できます。tpinit() が暗黙的に呼び出された場合、ヌル・パラメータによって呼び出された場合、またはフラグ・フィールドに TPMULTICONTEXTS を指定せずに呼び出された場合は、1 つのアプリケーションとの関連しか作成できません。
シングルコンテキスト・モードで tpinit() が 2 回以上呼び出された場合 (つまり、クライアントがアプリケーションに参加した後で呼び出された場合) は、アクションは何も実行されず、成功を示す戻り値が返されます。
マルチコンテキスト・モードの場合、tpinit() の呼び出しのたびに新しいアプリケーション関連が作成されます。アプリケーションは、tpgetctxt() を呼び出すことによって、このアプリケーション関連を表すハンドルを取得することができます。同じプロセス内のどのスレッドも、tpsetctxt() を呼び出してスレッドのコンテキストを設定することができます。
いったんアプリケーションでシングルコンテキスト・モードが選択された場合は、すべてのアプリケーション関連が終了するまで、すべての tpinit() 呼び出しでシングルコンテキスト・モードを指定する必要があります。同様に、アプリケーションでマルチコンテキスト・モードが選択された場合は、すべてのアプリケーション関連が終了するまで、すべての tpinit() 呼び出しでマルチコンテキスト・モードを指定する必要があります。
サーバ・プログラムは 1 つのアプリケーションとしか関連付けられないため、クライアントとして機能することはありません。ただし、各サーバ・プログラム内に、複数のサーバ・ディスパッチ・コンテキストがある場合もあります。各サーバ・ディスパッチ・コンテキストは、それぞれのスレッド内で機能します。
表 2 は、クライアント・プロセス内で発生する、非初期化状態、シングルコンテキスト・モードで初期化された状態、およびマルチコンテキスト・モードで初期化された状態の遷移を示しています。
クライアント・スレッドのコンテキスト状態の変化 マルチコンテキストのアプリケーションでは、いろいろな関数を呼び出すと、呼び出し元スレッドおよび呼び出し元プロセスと同じコンテキストでアクティブのその他のスレッドのコンテキスト状態が変化します。次の図は、tpinit()、tpsetctxt()、および tpterm() 関数を呼び出した場合のコンテキスト状態の変化を示しています。tpgetctxt() 関数を呼び出しても、コンテキスト状態は変化しません。 マルチコンテキスト状態の遷移
注記 tpterm() がマルチコンテキスト状態 (TPMULTICONTEXTS) で実行しているスレッドによって呼び出されると、呼び出し元スレッドはヌル・コンテキスト状態 (TPNULLCONTEXT) になります。終了するコンテキストに関連するその他すべてのスレッドは、無効コンテキスト状態 (TPINVALIDCONTEXT) に切り替わります。 表 3 は、tpinit()、tpsetctxt()、および tpterm() を呼び出した場合のコンテキスト状態の変化を示します。いずれの状態もスレッド固有のものであり、マルチコンテキストのアプリケーションの一部を構成するときは、スレッドごとに状態が異なります。一方、前掲の表 (「プロセスごとのコンテキスト・モード」) に示されるコンテキスト状態は、それぞれプロセス全体に適用されます。
スレッド・プログラミングのサポート BEA Tuxedo ATMI システムは、いくつかの方法でプログラミングされたマルチスレッド・プログラミングをサポートしています。プロセスでシングルコンテキスト・モードが使用されている場合に、アプリケーションで新しいスレッドが作成されると、これらのスレッドではそのプロセスの BEA Tuxedo ATMI コンテキストを共有します。クライアントでは、あるスレッドがシングルコンテキスト・モードで tpinit() 呼び出しを発行すると、他のスレッドは ATMI 呼び出しを発行します。たとえば、1 つのスレッドが tpacall() を発行すると、同じプロセス内の別のプロセスは tpgetrply() を発行します。 マルチコンテキスト・モードの場合、最初のスレッドは BEA Tuxedo ATMI アプリケーションに関連付けられません。スレッドは、tpsetctxt() を呼び出して既存のアプリケーション関連に参加するか、TPMULTICONTEXTS フラグを設定した tpinit() を呼び出して新しい関連を作成します。 シングルコンテキスト・モードかマルチコンテキスト・モードかに関わりなく、ATMI 操作が適切なタイミングで実行されるようにスレッドを調整するのは、アプリケーションの役目です。 アプリケーションは、OS スレッド関数を使って、アプリケーション・サーバ内に追加スレッドを生成できます。これらの新しいスレッドは、BEA Tuxedo ATMI システムから独立して動作できます。また、いずれかのサーバ・ディスパッチ・スレッドと同じコンテキストで動作することもできます。最初、アプリケーション生成サーバ・スレッドは、どのサーバ・ディスパッチ・コンテキストにも関連していません。アプリケーションに作成されたサーバ・スレッドは、tpsetctxt() を呼び出し、サーバ・ディスパッチ・スレッドとの関連を確立します。アプリケーションに作成されたサーバ・スレッドは、ディスパッチされたスレッドが tpreturn() または tpforward() を呼び出す前に、すべての ATMI 呼び出しを終了していなければなりません。BEA Tuxedo ATMI システムによってディスパッチされたサーバ・スレッドは、tpsetctxt() を呼び出すことはできません。また、アプリケーション生成スレッドは、コンテキストと関連付けられていない場合、暗黙的に tpinit() を発生させる ATMI を呼び出すことができません。それに対して、ディスパッチャによって作成されたスレッドは、常にコンテキストと関連付けられているため、ATMI 呼び出しに失敗することはありません。すべてのサーバ・スレッドで、tpinit() の呼び出しは禁止されています。 マルチスレッドのアプリケーションでは、TPINVALIDCONTEXT 状態で動作するスレッドが、多数の ATMI 関数を呼び出すことは禁止されています。次のリストは、このような環境で呼び出し可能な関数と呼び出し不可能な関数を示しています。 BEA Tuxedo ATMI システムでは、TPINVALIDCONTEXT 状態で動作するスレッドは以下の関数を呼び出すことができます。
BEA Tuxedo ATMI システムでは、TPINVALIDCONTEXT 状態で動作するスレッドは以下の関数を呼び出すことができません。
C 言語の ATMI の戻り値とその他の定義
ルーチンは、次に挙げる戻り値とフラグの定義を使用します。異なるトランザクション・モニタで変更や再コンパイルなしにアプリケーションを使用するためには、各システムで次に示すようにそのフラグと戻り値を定義しておかなければなりません。
/*
* 次の定義は atmi.h に含まれなければなりません
*/
/* サービス・ルーチンへのフラグ */
#define TPNOBLOCK 0x00000001 /* 非ブロック送信/受信 */
#define TPSIGRSTRT 0x00000002 /* 割り込み時受信再開 */
#define TPNOREPLY 0x00000004 /* 応答なしを期待 */
#define TPNOTRAN 0x00000008 /* トランザクション・モードでは送信しない */
#define TPTRAN 0x00000010 /* トランザクション・モードでの送信 */
#define TPNOTIME 0x00000020 /* タイムアウトなし */
#define TPABSOLUTE 0x00000040 /* 絶対的な優先順位の指定 */
#define TPGETANY 0x00000080 /* 有効応答の取り込み */
#define TPNOCHANGE 0x00000100 /* 受信バッファのマッチング */
#define RESERVED_BIT1 0x00000200 /* 将来の使用のために予約 */
#define TPCONV 0x00000400 /* 会話型サービス */
#define TPSENDONLY 0x00000800 /* 送信専用モード */
#define TPRECVONLY 0x00001000 /* 受信専用モード */
#define TPACK 0x00002000 /* */
/* tpreturn() へのフラグ - xa.h にも定義されている */
#define TPFAIL 0x20000000 /* tpreturn に対するサービスの FAILURE */
#define TPEXIT 0x08000000 /* サービスの終了によるサービスの FAILURE */
#define TPSUCCESS 0x04000000 /* tpreturn に対するサービスの SUCCESS */
/* tpscmt() へのフラグ - 有効な TP_COMMIT_CONTROL
* 特性値
*/
#define TP_CMT_LOGGED 0x01
/* コミット決定を記録後、リターン */
#define TP_CMT_COMPLETE 0x02
/* コミット完了後、リターン */
/* クライアント識別子構造 */
struct clientid_t {
long clientdata[4]; /* 内部での使用のため予約 */
}
typedef struct clientid_t CLIENTID;
/* クライアント識別子構造 */
typedef long TPCONTEXT_T;
/* サービス・ルーチンへのインターフェイス */
struct tpsvcinfo {
name[32];
long flags; /* サービス属性の説明 */
char *data; /* データを指すポインタ */
long len; /* 要求データ長 */
int cd; /* (flags TPCONV) が真のとき接続記述子 */
long appkey; /* アプリケーション認証用のクライアント・
* キー */
CLIENTID cltid; /* 発行元クライアント用の
* クライアント識別子 */
};
typedef struct tpsvcinfo TPSVCINFO;
/* tpinit(3) インターフェイス構造 */
#define MAXTIDENT 30
struct tpinfo_t{
char usrname[MAXTIDENT+2]; /* クライアント・ユーザ名 */
char cltname[MAXTIDENT+2]; /* アプリケーション・クライアント名 */
char passwd[MAXTIDENT+2]; /* アプリケーション・パスワード */
long flags; /* 初期化フラグ */
long datalen; /* アプリケーション固有のデータの長さ */
long data; /* アプリケーション・データのプレースホルダ */
};
typedef struct tpinfo_t TPINIT;
/* tpsuspend(3) と tpresume(3) に渡されるトランザクション ID 構造体 */
struct tp_tranid_t {
long info[6]; /*内部的に定義*/
};
typedef struct tp_tranid_t TPTRANID;
/* TPINIT のフラグ*/
#define TPU_MASK 0x00000007 /* 任意
* 通知型 */
#define TPU_SIG 0x00000001 /* シグナル・ベース
* の通知 */
#define TPU_DIP 0x00000002 /* ディップ・イン・ベース
* の通知 */
#define TPU_IGN 0x00000004 /* 任意通知型
* メッセージを無視 */
#define TPU_THREAD 0x00000040 /* THREAD 通知 */
#define TPSA_FASTPATH 0x00000008 /* システム・アクセス ==
* fastpath */
#define TPSA_PROTECTED 0x00000010 /* システム・アクセス ==
* protected */
#define TPMULTICONTEXTS 0x00000020 /* 各プロセスの
* マルチ・コンテキスト関連*/
/* /Q tpqctl_t データ構造体 */
#define TMQNAMELEN 15
#define TMMSGIDLEN 32
#define TMCORRIDLEN 32
struct tpqctl_t { /* キュー・プリミティブの制御パラメータ */
long flags; /* どの値が設定されているかの指示 */
long deq_time; /* キューから取り出すときの絶対時間/相対時間 */
long priority; /* 登録優先順位 */
long diagnostic; /* 異常終了の原因 */
char msgid[TMMSGIDLEN]; /* 既存メッセージの ID (そのメッセージの前に登録するため) */
char corrid[TMCORRIDLEN]; /* メッセージを識別するときに使用される相関識別子 */
char replyqueue[TMQNAMELEN+1]; /* 応答メッセージ用キューの名前 */
char failurequeue[TMQNAMELEN+1]; /* 異常終了メッセージ用キューの名前 */
CLIENTID cltid; /* 発信元クライアントの*/
/* クライアント識別子 */
long urcode; /* アプリケーション・ユーザ戻り値 */
long appkey; /* アプリケーション認証用のクライアント・キー */
long delivery_qos; /* 配信サービスの品質 */
long reply_qos; /* 応答メッセージのサービス品質 */
long exp_time /* 有効期限 */
};
typedef struct tpqctl_t TPQCTL;
/* 有効な /Q 構造体要素 - フラグに設定 */
#ifndef TPNOFLAGS
#define TPNOFLAGS 0x00000 /* フラグの設定なし―獲得できません */
#endif
#define TPQCORRID 0x00001 /* 相関 id の設定/獲得 */
#define TPQFAILUREQ 0x00002 /* 障害キューの設定/獲得 */
#define TPQBEFOREMSGID 0x00004 /* メッセージ id の前にキューに登録 */
#define TPQGETBYMSGIDOLD 0x00008 /* 使用回避*/
#define TPQMSGID 0x00010 /* enq/deq メッセージの msgid の獲得 */
#define TPQPRIORITY 0x00020 /* メッセージ優先順位の設定/獲得 */
#define TPQTOP 0x00040 /* キューの先頭に登録 */
#define TPQWAIT 0x00080 /* キューからの解除を待機 */
#define TPQREPLYQ 0x00100 /* 応答キューの設定/獲得 */
#define TPQTIME_ABS 0x00200 /* 絶対時間の設定 */
#define TPQTIME_REL 0x00400 /* 相対時間の設定 */
#define TPQGETBYCORRIDOLD 0x00800 /* 使用回避 */
#define TPQPEEK 0x01000 /* 非破壊的なキューからの取り出し */
#define TPQDELIVERYQOS 0x02000 /* 配信サービス品質*/
#define TPQREPLYQOS 0x04000 /* 応答メッセージのサービス品質*/
#define TPQEXPTIME_ABS 0x08000 /* 絶対有効期限 */
#define TPQEXPTIME_REL 0x10000 /* 相対有効期限*/
#define TPQEXPTIME_NONE 0x20000 /* 有効期限なし */
#define TPQGETBYMSGID 0x40008 /* msgid によるキューからの取り出し*/
#define TPQGETBYCORRID 0x80800 /* corrid によるキューからの取り出し */
/* TPQCTL 構造のサービス品質フィールドのための有効フラグ*/
#define TPQQOSDEFAULTPERSIST 0x00001 /* キューのデフォルトの持続性 */
/* 方針 */
#define TPQQOSPERSISTENT 0x00002 /* ディスク・メッセージ */
#define TPQQOSNONPERSISTENT 0x00004 /* メモリ・メッセージ */
/* エラー・リターン・コード */
extern int tperrno;
extern long tpurcode;
/* tperrno 値 - エラー・コード */
* マニュアル・ページで、下記のエラー・コードが返される可能性のある
* コンテキストに関する説明があります。
*/
#define TPMINVAL 0 /* 最小のエラー・メッセージ */
#define TPEABORT 1
#define TPEBADDESC 2
#define TPEBLOCK 3
#define TPEINVAL 4
#define TPELIMIT 5
#define TPENOENT 6
#define TPEOS 7
#define TPEPERM 8
#define TPEPROTO 9
#define TPESVCERR 10
#define TPESVCFAIL 11
#define TPESYSTEM 12
#define TPETIME 13
#define TPETRAN 14
#define TPGOTSIG 15
#define TPERMERR 16
#define TPEITYPE 17
#define TPEOTYPE 18
#define TPERELEASE 19
#define TPEHAZARD 20
#define TPEHEURISTIC 21
#define TPEEVENT 22
#define TPEMATCH 23
#define TPEDIAGNOSTIC 24
#define TPEMIB 25
#define TPMAXVAL 26 /* 最大のエラー・メッセージ */
/* 会話 - イベント */
#define TPEV_DISCONIMM 0x0001
#define TPEV_SVCERR 0x0002
#define TPEV_SVCFAIL 0x0004
#define TPEV_SVCSUCC 0x0008
#define TPEV_SENDONLY 0x0020
/* /Q 診断コード */
#define QMEINVAL -1
#define QMEBADRMID -2
#define QMENOTOPEN -3
#define QMETRAN -4
#define QMEBADMSGID -5
#define QMESYSTEM -6
#define QMEOS -7
#define QMEABORTED -8
#define QMENOTA QMEABORTED
#define QMEPROTO -9
#define QMEBADQUEUE -10
#define QMENOMSG -11
#define QMEINUSE -12
#define QMENOSPACE -13
#define QMERELEASE -14
#define QMEINVHANDLE -15
#define QMESHARE -16
/* イベント・ブローカ・メッセージ */
#define TPEVSERVICE 0x00000001
#define TPEVQUEUE 0x00000002
#define TPEVTRAN 0x00000004
#define TPEVPERSIST 0x00000008
/* サブスクリプション制御構造 */
struct tpevctl_t {
long flags;
char name1[XATMI_SERVICE_NAME_LENGTH];
char name2[XATMI_SERVICE_NAME_LENGTH];
TPQCTL qctl;
};
typedef struct tpevctl_t TPEVCTL;
C 言語の TX の戻り値とその他の定義
TX ルーチンは、次に挙げる戻り値とフラグの定義を使用します。異なるトランザクション・モニタで変更や再コンパイルなしにアプリケーションを使用するためには、各システムで次に示すようにそのフラグと戻り値を定義しておかなければなりません。
#define TX_H_VERSION 0 /* このヘッダ・ファイルの
* 現バージョン */
/*
* トランザクション識別子
*/
#define XIDDATASIZE 128 /* サイズ (バイト数) */
struct xid_t {
long formatID; /* 形式識別子 */
long gtrid_length; /* 64 以下の値 */
long bqual_length; /* 64 以下の値 */
char data[XIDDATASIZE];
};
typedef struct xid_t XID;
/*
* 形式識別子が -1 の場合は、XID がヌルであることを意味する
*/
/*
* tx_ ルーチンの定義
*/
/* commit の戻り値 */
typedef long COMMIT_RETURN;
#define TX_COMMIT_COMPLETED 0
#define TX_COMMIT_DECISION_LOGGED 1
/* トランザクション制御の値 */
typedef long TRANSACTION_CONTROL;
#define TX_UNCHAINED 0
#define TX_CHAINED 1
/* トランザクション・タイムアウトのタイプ */
typedef long TRANSACTION_TIMEOUT;
/* トランザクションの状態値 */
typedef long TRANSACTION_STATE;
#define TX_ACTIVE 0
#define TX_TIMEOUT_ROLLBACK_ONLY 1
#define TX_ROLLBACK_ONLY 2
/* tx_info() で格納される構造体 */
struct tx_info_t {
XID xid;
COMMIT_RETURN when_return;
TRANSACTION_CONTROL transaction_control;
TRANSACTION_TIMEOUT transaction_timeout;
TRANSACTION_STATE transaction_state;
};
typedef struct tx_info_t TXINFO;
/*
* tx_() の戻り値
* (トランザクション・マネージャがアプリケーションに報告する)
*/
#define TX_NOT_SUPPORTED 1 /* サポートされていないオプション */
#define TX_OK 0 /* 正常実行 */
#define TX_OUTSIDE -1 /* アプリケーションは、リソース・マネージャの
* ローカル・トランザクションにある */
#define TX_ROLLBACK -2 /* トランザクションが
* ロールバックされた */
#define TX_MIXED -3 /* トランザクションが
* 部分的にコミットされ、
* 部分的にロールバックされた */
#define TX_HAZARD -4 /* トランザクションが
* 部分的にコミットされ、
* 部分的にロールバックされた可能性がある */
#define TX_PROTOCOL_ERROR -5 /* ルーチンが不適切な
* コンテキストで呼び出された */
#define TX_ERROR -6 /* 一時的なエラー */
#define TX_FAIL -7 /* 致命的なエラー */
#define TX_EINVAL -8 /* 無効な引数が指定された */
#define TX_COMMITTED -9 /* トランザクションが
* ヒューリスティックにコミットされた */
#define TX_NO_BEGIN -100 /* トランザクションがコミットされたことに加え、
* 新しいトランザクションが
* 開始できなかった */
#define TX_ROLLBACK_NO_BEGIN (TX_ROLLBACK+TX_NO_BEGIN)
/* トランザクションがロールバックされたことに加え、
* 新しいトランザクションが
* 開始できなかった */
#define TX_MIXED_NO_BEGIN (TX_MIXED+TX_NO_BEGIN)
/* 混合条件が発生したことに加え、
* 新しいトランザクションが開始できなかった */
#define TX_HAZARD_NO_BEGIN (TX_HAZARD+TX_NO_BEGIN)
/* ハザードがあることに加え、
* 新しいトランザクションが開始できなかった */
#define TX_COMMITTED_NO_BEGIN (TX_COMMITTED+TX_NO_BEGIN)
/* トランザクションがヒューリスティックにコミットされたことに加え、
* 新しいトランザクションが
* 開始できなかった */
ATMI の状態遷移
BEA Tuxedo ATMI システムは、各プロセスの状態を記録し、各種の関数呼び出しやオプションごとに正当な状態遷移が行われているかどうかを検証します。この状態情報には、プロセスのタイプ (要求/応答型サーバ、会話型サーバ、またはクライアント)、初期化状態 (初期化済み、非初期化)、リソースの管理状態 (クローズまたはオープン)、プロセスのトランザクション状態およびすべての非同期要求および接続記述子の状態などがあります。不正な状態遷移が行われようとすると、呼び出された関数は異常終了し、tperrno() が TPEPROTO に設定されます。この情報に関する正規の状態と遷移について、次の表に示します。
表 4 は、要求/応答型サーバ、会話サーバおよびクライアントがどの関数を呼び出すことができるかを示しています。ただし、tpsvrinit()、tpsvrdone()、tpsvrthrinit()、および tpsvrthrdone() はこの表には示してありません。これらの関数はアプリケーションが提供する関数ですが、アプリケーションからは呼び出されず、BEA Tuxedo ATMI システムによって呼び出されます。
関数 |
プロセス・タイプ |
||
---|---|---|---|
要求/応答型サーバ |
会話型サーバ |
クライアント |
|
tpabort |
Y |
Y |
Y |
tpacall |
Y |
Y |
Y |
tpadvertise |
Y |
Y |
N |
tpalloc |
Y |
Y |
Y |
tpbegin |
Y |
Y |
Y |
tpbroadcast |
Y |
Y |
Y |
tpcall |
Y |
Y |
Y |
tpcancel |
Y |
Y |
Y |
tpchkauth |
Y |
Y |
Y |
tpchkunsol |
N |
N |
Y |
tpclose |
Y |
Y |
Y |
tpcommit |
Y |
Y |
Y |
tpconnect |
Y |
Y |
Y |
tpdequeue |
Y |
Y |
Y |
tpdiscon |
Y |
Y |
Y |
tpenqueue |
Y |
Y |
Y |
tpforward |
Y |
N |
N |
tpfree |
Y |
Y |
Y |
tpgetctxt |
Y |
Y |
Y |
tpgetlev |
Y |
Y |
Y |
tpgetrply |
Y |
Y |
Y |
tpgprio |
Y |
Y |
Y |
tpinit |
N |
N |
Y |
tpnotify |
Y |
Y |
Y |
tpopen |
Y |
Y |
Y |
tppost |
Y |
Y |
Y |
tprealloc |
Y |
Y |
Y |
tprecv |
Y |
Y |
Y |
tpresume |
Y |
Y |
Y |
tpreturn |
Y |
Y |
N |
tpscmt |
Y |
Y |
Y |
tpsend |
Y |
Y |
Y |
tpservice |
Y |
Y |
N |
tpsetctxt |
Y (アプリケーション生成スレッドの場合) |
Y (アプリケーション生成スレッドの場合) |
Y |
tpsetunsol |
N |
N |
Y |
tpsprio |
Y |
Y |
Y |
tpsubscribe |
Y |
Y |
Y |
tpsuspend |
Y |
Y |
Y |
tpterm |
N |
N |
Y |
tptypes |
Y |
Y |
Y |
tpunadvertise |
Y |
Y |
N |
tpunsubscribe |
Y |
Y |
Y |
以下に示す表は、特に明記されていないかぎり、クライアントとサーバ両方に適用されます。なお、ある種の関数はクライアントとサーバの両方が呼び出せるとは限らないので(例: tpinit()、以下の状態遷移の中には両方のプロセス・タイプには適用できないものがあります)上記の表を参照して、目的のプロセスから特定の関数を呼び出すことができるかどうかを判断するようにしてください。 次の表は、クライアント・プロセスがトランザクション・マネージャで初期化され登録されているかどうかを示しています。この表では、シングルコンテキスト・モードのオプションとして tpinit() を使用するものとします。したがって、シングルコンテキストのクライアントは、多数の ATMI 関数の中のどれか (たとえば、tpconnect() または tpcall()) を発行することによって、暗黙のうちにアプリケーションを結合することができます。次のいずれかにあてはまる場合は、クライアントは tpinit() を使用しなければなりません。
サーバは tpsvrinit() 関数が呼び出される前に BEA Tuxedo ATMI システムによって初期化状態になり、tpsvrdone() 関数が返された後、BEA Tuxedo ATMI システムの main() によって非初期化状態になります。なお、下記のすべての表において、関数がエラーを起こした場合、特に明記されていないかぎり、プログラムの状態は変わりません。
以降の表は、前提条件として状態が I1 であると想定しています (tpinit()、tpsetctxt()、または BEA Tuxedo ATMI システムの main() を介してこの状態でプロセスが到着したかどうかに関わりなく)。 表 6は、クライアントまたはサーバのプロセスに対応するリソース・マネージャが初期化されているかいないかに応じて、そのプロセスの状態を示しています。
関数 |
状態 |
|
---|---|---|
クローズ |
オープン |
|
tpopen |
R1 |
R1 |
tpclose |
R0 |
R0 |
tpbegin |
|
R1 |
tpcommit |
|
R1 |
tpabort |
|
R1 |
tpsuspend |
|
R1 |
tpresume |
|
R1 |
フラグ TPTRAN オンの tpservice |
|
R1 |
他のすべての ATMI 関数 |
R0 |
R1 |
表 7は、プロセスがトランザクションに対応しているかどうかに関してそのプロセスの状態を示したものです。サーバの場合、状態 T1 と T2 への遷位は、事前条件として状態 R1 を想定しています (たとえば、tpopen() はそれ以降 tpclose() または tpterm() への呼び出しがないものとして呼び出されています)。
表 8は、tpacall() が返す 1 つの要求記述子の状態を示すものです。
関数 |
状態 |
|
---|---|---|
記述子なし A0 |
有効な記述子 A1 |
|
tpacall |
A1 |
|
tpgetrply |
|
A0 |
tpcancel |
|
A0a |
tpabort |
A0 |
A0 b |
tpcommit |
A0 |
A0 b |
tpsuspend |
A0 |
A1 c |
tpreturn |
A0 |
A0 |
tpforward |
A0 |
A0 |
tpterm |
I0 |
I0 |
他のすべての ATMI 関数 |
A0 |
A1 |
注記 a この状態遷移は、記述子が呼び出し元のトランザクションに対応しない場合にのみ起こります。 b この状態遷移は、記述子が呼び出し元のトランザクションに対応する場合にのみ起こります。 c 記述子が呼び出し元のトランザクションに対応する場合、tpsuspend() はプロトコル・エラーを返します。 表 9は、tpconnect() が返す、あるいは TPSVCINFO 構造でサービス呼び出しを行うことによって得られる接続記述子の状態を示したものです。接続記述子をとらないプリミティブの場合、特に明記されていないかぎり、状態の変化はすべての接続記述子に適用されます。 状態には次のものがあります。
注記 a プログラムがトランザクション・モードにあり、かつ TPNOTRAN の指定がない場合は、接続はトランザクション・モードになります。
b TPTRAN が設定されていると、接続はトランザクション・モードになります。
c 接続がトランザクション・モードにないと、状態は変化しません。
d 接続がトランザクション・モードの場合、tpsuspend() はプロトコル・エラーを返します。
TX の状態遷移
BEA Tuxedo ATMI システムでは、プロセスが必ず TX 関数を正しい順序で呼び出すことが確認されます。不正の状態遷移が試行されると (つまり、ブランクの遷移エントリの状態からの呼び出し)、呼び出された関数は、TX_PROTOCOL_ERROR を返します。TX 関数の正当な状態と遷移を、表 10に示します。異常終了を返す呼び出しの場合、この表で特に明記されていないかぎり、状態遷移は行われません。BEA Tuxedo ATMI システムのクライアントまたはサーバはすべて、TX 関数を使用できます。
状態は、次のように定義されています。
関連項目
buffer(3c)、 tpadvertise(3c)、 tpalloc(3c)、 tpbegin(3c)、 tpcall(3c)、 tpconnect(3c)、 tpgetctxt(3c)、 tpinit(3c)、 tpopen(3c)、 tpservice(3c)、 tpsetctxt(3c)、 tuxtypes(5)、 typesw(5)
|
Copyright © 2001 BEA Systems, Inc. All rights reserved.
|