bea ホーム | 製品 | dev2dev | support | askBEA |
![]() |
![]() |
|
![]() |
e-docs > Tuxedo > TxRPC を使用した Tuxedo アプリケーションのプログラミング > RPC クライアント/サーバ・プログラムの作成 |
TxRPC を使用した Tuxedo アプリケーションのプログラミング
|
RPC クライアント/サーバ・プログラムの作成
ここでは、次の内容について説明します。
注記 クライアントおよびサーバのソース・ファイルのサンプルについては、アプリケーション例を参照してください。
リモート処理への対応
TxRPC の目的は、あるアドレス空間にあるクライアントと別のアドレス空間にあるサーバとの間で、透過的なプロシージャ・コールを提供することです。クライアントとサーバは、別のマシンに存在する場合もあります。ただし、クライアントとサーバのアドレス空間が異なるので、次のような点に注意する必要があります。
返されるステータスと例外の処理
X/OPEN RPC 仕様では、アプリケーション以外のエラーは状態パラメータまたは状態復帰で返されます。RPC サーバに障害があった場合には fault_status 値が返され、通信に障害があった場合には comm_status 値が返されます。状態復帰を指定するには、IDL ファイルでオペレーションの戻り値または error_status_t 型の [out] パラメータを定義します。さらにACF ファイルで、そのオペレーションまたはパラメータが [fault_status] または [comm_status] のいずれか、あるいは両方の属性を持つことを宣言します。
たとえば、IDL ファイル内で次のようにオペレーションを定義します。
error_status_t op([in,out]long *parm1, [out]error_status_t *commstat);
対応する ACF ファイル内での定義は次のようになります。
[fault_status]op([comm_status]commstat);
サーバからのエラーは、オペレーションの戻り値に、通信エラーは 2 番目のパラメータに返されます。クライアント・コードでは、以下のようにエラーを処理します。
if (op(&parm1, &commstat) != 0 || commstat != 0) /* エラーの処理 */
状態復帰を使用する利点は、エラー発生個所で対処が行え、きめ細かなエラー回復処理を実行できることです。
状態復帰の欠点は、ローカル版の関数には必要のないパラメータをリモート関数に付加することです。さらに、きめ細かなエラー回復処理は冗長になりがちで、エラーを引き起こす傾向があります (たとえば、場合分けに見落としが生じるなど)。
DCE は第 2 のメカニズムとして例外処理を定義しています。この例外処理は C++ のものと類似しています。
C や C++ のアプリケーション・コードを TRY、CATCH、CATCH_ALL、および ENDTRY ステートメントを用いて、例外が生じる可能性のあるブロックに区切ります。TRY はブロックの開始を示します。CATCH は、特定の例外用の処理ブロックを示します。CATCH_ALL は、対応する CATCH ステートメントを持たない例外を処理するために使われます。ENDTRY でブロックを終了します。例外処理が低いレベルでは行なえず、RERAISE ステートメントを用いて高いレベルのブロックで例外処理を行う場合、TRY ブロックはネストされます。例外処理ブロックの外部で例外が生じた場合は、プログラムはログにメッセージを記録して終了します。例外処理マクロの詳細と使用例については、『BEA Tuxedo C リファレンス』の TRY(3c) を参照してください。
RPC コールに対して通信とサーバで生成される例外のほかに、さらに低いレベルの例外、特に、オペレーティング・システムのシグナルも生成されます。このような例外の詳細については、『BEA Tuxedo C リファレンス』の TRY(3c) を参照してください。
スタブ・サポート関数の使用
X/OPEN 仕様では、100 を越える膨大な数のランタイム・サポート関数が定義されています。これらの関数を、X/OPEN TxRPC IDL-only 環境ですべてサポートする必要はありません。これらの関数の大部分は、BEA Tuxedo のクライアントやサーバに対して透過的に行われるバインディングと管理に関連したものです。
アプリケーションの移植性に影響を及ぼす事柄の 1 つに、スタブ用の入出力パラメータと戻り値に割り当てられるメモリの管理があります。Stub Memory Management ルーチンは、スレッドを扱う 2 つの関数を除き TxRPC ランタイムでサポートされています。状態を返す関数には以下のものがあります。
同等の例外を返す関数には以下のものがあります。
これらの関数の詳細については、『BEA Tuxedo C リファレンス』を参照してください。
ランタイム関数は、libtrpc ファイルに含まれます。RPC クライアントとサーバの作成方法については次トピックで解説します。
メモリ管理を効果的に行う方法を次に示します。
rpc_ss_set_client_alloc_free(rpc_ss_allocate, rpc_ss_free);
ptr = remote_call_returns_pointer();
/* 返されたポインタをここで使用 */
...
rpc_ss_disable_allocate(); /* ptr を解放 */
rpc_ss_set_client_alloc_free(rpc_ss_allocate, rpc_ss_free);
long *ptr;
ptr = (long *)rpc_ss_allocate(sizeof(long));
RPC ヘッダ・ファイルの使用
DCE/RPC と Tuxedo/TxRPC 両方からのスタブが同一環境で確実にコンパイルできるようにするため、Tuxedo/TxRPC のインプリメンテーションで用いるヘッダ・ファイル名は異なるものにします。これらのヘッダ・ファイルは IDL コンパイラが生成するインターフェイス・ヘッダ・ファイルに自動的にインクルードされるので、アプリケーション・プログラマには影響を与えません。ただし、型や関数の定義方法を調べるために、アプリケーション・プログラムでこれらのヘッダ・ファイルを表示することは可能です。以下に、RPC における新しいヘッダ・ファイル名のリストを示します。
ヘッダ・ファイルは $TUXDIR/include/rpc ディレクトリにあります。デフォルトでは、Tuxedo/TxRPC IDL コンパイラは「システム IDL ディレクトリ」として $TUXDIR/include を検索します。
コードの移植性
IDL コンパイラからの出力は、多数の環境でコンパイルできるように作成されます。コンパイル作業の説明は次章を参照してください。ただし、環境によっては動作に支障が起きる構成もあります。既知の問題点を以下に示します。
ANSI に準拠しない旧形式の C 言語を使用してコンパイルする場合、「配列へのポインタ」は許可されません。次に例を示します。
typedef long array[10][10];
func()
{
array t1;
array *t2;
t2 = &t1; /* & ignored, invalid assignment */
func2(&t1); /* & ignored */
}
このため、移植を考慮した場合、「配列へのポインタ」をパラメータとして、オペレーションに渡すことが難しくなります。
文字列属性がマルチ・バイト構造体に適用されるところに、文字列の配列を使用すると、コンパイラが構造体に文字を埋め込むときに、期待する結果が得られないことがあります。これは通常は起こり得ません。ほとんどのコンパイラは文字フィールドのみを含む構造体には文字の埋め込みは行いません。しかし、この現象は少なくとも一度確認されています。
デフォルトでは、定数値のインプリメントは各定数に対して #define を作成することで行われます。このため、定数に用いる名前は、IDL ファイル内やインポートされたすべての IDL ファイル内のほかのすべての名前と同じ名前にしてはいけません。ANSI C 環境でこの問題を回避するには、tidl コンパイラの TxRPC 固有のオプション _use_const を使用します。このオプションを使うと、#define 定義の代わりに、const 宣言が作成されます。定数値はクライアント・スタブとサーバ・スタブ内で宣言されます。ヘッダ・ファイルをインクルードするほかのすべてのソース・ファイルでは、単に extern const 宣言が使用されます。こうしないと、クライアント・スタブとサーバ・スタブを同一の実行ファイルにコンパイルできないという制限を生じるか、二重定義エラーが発生することに注意してください。
C++ 環境では、次のような制限があります。
struct t1 {
long s1;
};
typedef struct t1 t1; /* 正常 */
typedef long t1; /* エラー */
struct t1 {
struct t2 {
long s2;
} s1;
} t1;
typedef struct t3 {
struct t2 s3; /* t2 は未定義エラー */
} t3;
long *ptr;
ptr = (long *)malloc(sizeof(*ptr) * 4);
クライアントとサーバのアプリケーション・ソフトウェアをコーディングしているときは、IDL コンパイラが作成したデータ型、すなわち rpc/tidlbase.h 内で定義されるデータ型を使う必要があります (rpc/tidlbase.h 内での定義とは、次の表に「発行されるマクロ」として記載されているものです)。たとえば、idl_long_int の代わりに long を使うと、データ型はプラットフォームによっては 32 ビットであったり 64 ビットであったりします。一方、idl_long_int は全プラットフォームで 32 ビットです。作成されるデータ型の一覧を表 3-1 に示します。
C の場合と同様、IDL でも複数のクラスの識別子があります。スコープや名前空間などのクラス内では、名前を一意にする必要があります。
タグを持たず、typedef の一部として定義されていない匿名の構造体または共用体は、オペレーションの戻り値やパラメータとして使用できないことに注意してください。
ATMI との対話
TxRPC 実行プログラムは BEA Tuxedo システムを使って RPC 通信を行います。その他の BEA Tuxedo のインターフェイスや通信メカニズムは、RPC 呼び出しを使用している同一のクライアントおよびサーバ内で使用できます。このため、単一のクライアントが要求/応答呼び出し (例:tpcall(3c)、tpacall(3c)、tpgetrply(3c))、会話型呼び出し (tpconnect(3c)、tpsend(3c)、tprecv(3c)、tpdiscon(3c)) を行い、安定キューにアクセス (tpenqueue(3c) および tpdequeue(3c)) することが可能です。クライアントが、BEA Tuxedo ソフトウェアを最初に呼び出すときに、自動的にアプリケーションに参加します。クライアントが最初に行う呼び出しは、RPC 呼び出し、その他の通信呼び出し、ATMI 呼び出し (例 : バッファ割り当て、任意通知など) です。ただし、アプリケーションがセキュリティをオンにした状態で実行していたり、あるいはクライアントが特定のリソース・マネージャ・グループの一部として稼働する必要がある場合は、関数 tpinit(3c) を明示的に呼び出してアプリケーションに参加しなければなりません。明示的に設定できるオプションの詳細と一覧については、『BEA Tuxedo C リファレンス』の tpinit(3c) を参照してください。アプリケーションが BEA Tuxedo システムを使用した作業を完了する場合には、関数 tpterm(3c) を明示的に呼び出してアプリケーションを終了し、関連のあるリソースをすべて解放する必要があります。ワークステーション以外のネイティブなクライアントに対してこの明示的な呼び出しが行われなかった場合、モニタがこれを検知し、userlog(3c) に警告を出力し、リソースを解放します。クライアントがワークステーションの場合は、リソースは解放されず、結果的にワークステーションのリスナまたはハンドラがリソースを使い果たし、新たなクライアントを受け付けることができなくなります。
クライアントと同様に、サーバはクライアントのロール内の任意の通信パラダイムを使用できます。ただし、同一サーバ内では会話型サービスと RPC サービスの両方を提供 (宣言) することはできません。後で説明するように、RPC サーバは非会話型として指定する必要があります。ATMI 要求/応答と RPC サービスを同一サーバ内で混用することは可能ですが、お勧めできません。その他の制限として、RPC オペレーションは関数 tpreturn(3c) や関数 tpforward(3c) を呼び出すことはできません。RPC オペレーションは、ローカルに呼び出された場合と同様の復帰動作で復帰する必要があります。RPC オペレーションから関数 tpreturn(3c) や関数 tpforward(3c) の呼び出しを試みると、その呼び出しはインターセプトされ、クライアントにエラーが返されます (例外 rpc_x_fault_unspec または状態 rpc_s_fault_unspec)。
サーバでは利用できますが、クライアントでは利用できない関数が 2 つあります。関数 tpsvrinit(3c) と関数 tpsvrdone(3c) がこれにあたります。それぞれサーバの起動時とシャットダウン時に呼び出されます。サーバは、TxRPC オペレーション要求を受け取る前に、tx_open(3c) を呼び出す必要があるので、tpsvrinit() で tx_open を呼び出すことをお勧めします。デフォルトの tpsvrinit() 関数は関数 tx_open() を呼び出しています。
TX との対話
TX 関数は、トランザクションの境界用のインターフェイスを提供します。関数 tx_begin(3c) と、tx_commit(3c) または tx_rollback(3c) は、通信を含むトランザクション内のすべての作業をカプセル化します。その他のプリミティブとして、トランザクションのタイムアウト設定、連鎖または非連鎖としてのトランザクションの宣言、トランザクション情報の取得も提供されています。以上についての詳細は、X/OPEN TX 仕様に記載され、また X/OPEN TxRPC 仕様にも解説されています。X/OPEN TxRPC 仕様には、TX と RPC の相互動作についての解説があります。その要点を次に述べます。
TxRPC 仕様で定義された IDL に対するその他の変更と制限については、IDL に関する項で既に説明しました。
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |