ヘッダーをスキップ
TxRPCを使用したOracle Tuxedoアプリケーションのプログラミング
  目次へ移動
目次

前
 
次
 

1 TxRPCの紹介

ここでは、次の内容について説明します。

TxRPCとは

xRPC機能により、プログラマはリモート・プロシージャ・コール(RPC)インタフェースを使用できます。つまり、クライアント・プロセスは、ローカル関数呼出しを使用しているほかのプロセス内で、リモート関数(リモート・サービス)を呼び出すことができます。アプリケーションの作成者は、オペレーション(プロシージャ)と、インタフェース定義言語(IDL: Interface Definition Language)を使用してこれらのオペレーションに対してパラメータとして渡されるデータ型を指定する必要があります。オペレーションは1つのインタフェースにまとめられます。IDLコンパイラを使用して、スタブと呼ばれる代替プロシージャを生成します。このスタブを使用して、オペレーションをリモートで実行できます。まず理解する必要のある重要な概念は、2つの基本的なネーミングのレベルがあることです。まず、インタフェースが名前を持ち、1つのインタフェース内で1つ以上のオペレーションに名前が付けられます。インタフェースは、実行時に利用可能になります。つまり、インタフェース内のすべてのオペレーションが呼出し可能になります。個別のオペレーションを利用可能にする必要がある場合は、固有のインタフェース内でオペレーションを定義します。

次の図は、RPCがローカル・プロシージャ・コールのように見える方法を示しています。

図1-1 RPCの通信

図1-1の説明が続きます

クライアント・アプリケーション・コードは、IDLファイル内で定義されたオペレーション(関数)群の1つを呼び出します。サーバー・サイドにある実際の関数を呼び出すかわりに、クライアント・スタブが呼び出されます。データ型とオペレーションを定義するIDL入力ファイルに基づいて、IDLコンパイラがクライアント・スタブを作成します。入力パラメータ、戻り値の型、出力パラメータは、オペレーションごとに定義されます。クライアント・スタブは入力パラメータを受け取り、それらを単一のデータ・バッファに変換し、そのデータをサーバーに送ってレスポンスを待ちます。その後サーバーが戻り値および出力パラメータとして返したバッファ形式のデータをアンパックします。クライアント・プロセスとサーバー・プロセス間の通信は、マシン内、マシン間のいずれでもOracle Tuxedo ATMIランタイムで処理されます。

サーバー・サイドでは、ランタイムがインタフェースのサーバー・スタブを呼び出します。サーバー・スタブもIDLコンパイラが生成します。サーバー・スタブは入力パラメータを含むデータ・バッファをアンパックします。場合によってはサーバー・スタブは、オペレーションの出力パラメータに必要な領域を割り当て、オペレーションを呼び出して復帰を待ち、戻り値と出力パラメータを1つのバッファ内にパックしてクライアントにレスポンスを返します。

アプリケーションからは、単純なローカル・プロシージャ・コールが行われているように見えます。スタブとランタイムは、ローカルなアドレス空間(プロセス)以外のリモート・プロシージャの呼出しを隠ぺいします。

リモート・プロシージャ・コールを使用するアプリケーションを作成する手順は、これらのコールを用いない場合のアプリケーションの作成手順とほぼ同じです。大部分の時間はクライアントとサーバー用のアプリケーション、つまり実際にアプリケーションが行う作業のコーディングに費やされるでしょう。Oracle Tuxedo ATMIランタイムにより、アプリケーション・プログラマは、通信やクライアント・マシンで使用しているデータ形式からサーバー・マシンで使用しているデータ形式への変換などを配慮しなくて済みます。サーバー間の通信にTxRPCを使うこともできます。

単体型アプリケーションを作成する手順以外に、クライアントとサーバー間のインタフェースを完全に定義する手順も必要になります。前述のように、インタフェースにはリモート・プロシージャ・コールに用いるデータ型とオペレーションの定義が含まれます。通常、インタフェースの定義を含むファイル名には拡張子.idlを付けます。この規則に従えば、ファイルの種類がわかります。

すべてのインタフェースはそれぞれユニークな識別子を持つ必要があります。この汎用一意識別子(UUID:Universal Unique Identifier)は、128ビットで構成され、すべてのインタフェース間でそのインタフェースを一意に識別します。アプリケーション・プログラマは、uuidgenプログラムを実行してUUIDを生成します。uuidgenプログラムに-iオプションを指定して実行すると、新たなUUIDを含むインタフェース・テンプレートが作成されます。「アプリケーション例」に簡単なRPCアプリケーションのコードを含む開発例を示しています。この例では、最初の手順としてuuidgenコマンドの実行方法とその出力結果を示しています。uuidgenコマンドのその他のオプションについては、uuidgen(1)のマニュアル・ページを参照してください。

実行時にこのUUIDを使用して、クライアント・スタブが受信側のサーバー・スタブと一致することを確認します。つまり、UUIDは、Oracle Tuxedo ATMIランタイムが検証するためにクライアントからサーバーに送られるもので、アプリケーション・プログラマに対しては透過的です。

UUIDの検証以外にも、各インタフェースはインタフェースに関連付けられたバージョン番号をも持っています。このバージョン番号はメジャー番号とマイナー番号から構成されます。バージョン番号がインタフェース定義の一部として指定されない場合、デフォルトで0.0に設定されます。そのため、同じインタフェースに対して利用できるバージョンが複数存在する可能性があります。クライアントは、特定のバージョンのインタフェースから作成されたスタブ内のRPCを呼び出すことにより、特定のバージョンのインタフェースをリクエストします。バージョンが異なっていることは、データ型、オペレーション・パラメータ、または戻り値が変更されているか、あるいはそのインタフェースにオペレーションが追加、削除されたことを意味します。このため、RPCを正常に実行するには、クライアントとサーバーのUUIDおよびバージョンが一致している必要があります。アプリケーション・プログラマは、同じバージョン番号を持つインタフェースには、同じインタフェースまたは互換性のあるインタフェースを提供する必要があります。

uuidgenによってテンプレートIDLが作成された後、アプリケーション・プログラムは、そのインタフェース内のすべてのデータ型およびオペレーションを定義する必要があります。この言語は、プロシージャ・ステートメントがないCやC++の宣言部によく似ています。typedefステートメントでデータ型を宣言し、関数プロトタイプでオペレーションを宣言します。さらに情報を追加する場合はIDL属性を用います。この言語では、属性指定は[in]のように角カッコで囲みます。属性を使用して、実行時にポインタをNULLにできるかどうかなどのポインタの形式に関する情報や、パラメータが入力、出力、またはその両方のいずれかなどのパラメータに関係する情報を提供できます。IDL言語および関連するコンパイラの詳細は、「インタフェース定義言語(IDL)の使用」で説明します。

IDLファイルのほかに、インタフェースの追加属性を指定するために、オプションのACF (Attribute Configuration File)も用意されています。各RPCオペレーションのステータスを返すために、ステータス変数をオペレーション内で定義することが最も重要です。ステータス変数の使用法の詳細は、第3章「RPCクライアント/サーバー・プログラムの作成」で説明します。ACFファイル内の属性は、IDLファイル内の属性とは異なり、クライアントとサーバー間の通信には影響を与えませんが、アプリケーション・コードと、生成されたスタブとの間のインタフェースに影響を及ぼします。

Oracle Tuxedo ATMIランタイム使用時には、クライアントとサーバーのバインド(接続)の管理は透過的に行われます。クライアントやサーバーのアプリケーション・コードからは、クライアントとサーバーのバインドを管理するための情報は得られません。対称的に、OSF DCEランタイム使用時には、バインド管理のためにプログラマにかかる負担は大変なものがあります。Oracle Tuxedo ATMIランタイムはOSF DCEランタイム関数をサポートしていません。IDLやACFファイル内のバインド属性は無視します。

IDLファイルおよびオプションのACFファイルは、IDLコンパイラを使って「コンパイル」されます。コンパイラはまずヘッダー・ファイルを作成します。このヘッダー・ファイルには、IDLファイル内で定義されたオペレーションの型定義と関数プロトタイプがすべて含まれます。インタフェース内で定義されたRPCを呼び出すアプリケーション内でヘッダー・ファイルをインクルードできます。入力ファイルがfile.idlfile.acfであれば、デフォルトのヘッダー・ファイルの名前はfile.hになります。コンパイラはクライアントとサーバーの両方のスタブ・コードを作成します(例: file_cstub.cfile_sstub.c)。これらのスタブ・ファイルは前述したように、データのパッケージ処理とRPCの通信処理を含みます。デフォルトでは、IDLコンパイラはCコンパイラを起動し、クライアントとサーバーのスタブ・オブジェクト・ファイル(例:file_cstub.oおよびfile_sstub.o)を作成します。 その後、スタブ・ソース・ファイルは削除されます。IDLコンパイラには、リクエスト、生成の制限、ソースおよびオブジェクト・ファイルの保持、および出力ファイル名やディレクトリの変更を行うための、様々なオプションがあります。詳細は、tidl(1)のリファレンス・ページを参照してください。

インタフェースの定義が完了した後の大部分の作業はアプリケーション・コードを記述することです。クライアント・コードでは、インタフェース内で定義されたオペレーションを呼び出します。サーバー・コードではそのオペレーションを実装する必要があります。サーバーは、RPCを呼び出すことにより、クライアントとしても動作できる事に注意してください。アプリケーションを作成する上での注意事項については、「インタフェース定義言語(IDL)の使用」でより詳細に解説します。

アプリケーション・コードが完成すると、いよいよそのコードをコンパイルしてOracle Tuxedo ATMIランタイムとリンクします。このプロセスを簡略化するためのプログラムが2つ用意されています。それは、サーバー用のbuildserverとクライアント用のbuildclientです。これらのプログラムを使用して任意のソース・ファイルをコンパイルし、Oracle Tuxedo ATMIランタイムを使用して、コンパイルされたオブジェクトとライブラリ・ファイルをリンクして実行形式のファイルを作成します。これらのプログラムでは代替のコンパイラやコンパイラ・オプションを指定することもできます。詳細はbuildserver(1)buildclient(1)のリファレンス・ページを参照してください。

サーバーとクライアントを作成するプロセス全体を図1-2図1-3に示します。異なるプラットフォーム上でのクライアントとサーバー・プログラムの作成については、「RPCクライアント/サーバー・プログラムの構築」を参照してください。

図1-2 RPCサーバーの構築方法

図1-2については周囲のテキストで説明しています。

図1-2はサーバーを作成するプロセスを示します。

  1. uuidgenを実行し、UUIDを持つスケルトンのIDLファイル(simp.idl)を生成します。テンプレートIDLファイルを編集し、インタフェース定義言語を使用してクライアントとサーバー間のインタフェースを定義します。

  2. simp.idlおよびオプションのsimp.acfを使ってIDLコンパイラ(tidl)を実行し、インタフェース・ヘッダー・ファイルとサーバー・スタブ・オブジェクト・ファイルを生成します。

  3. サーバーのアプリケーション・コード(server.c)を記述した後、buildserverを実行し、そのコードをコンパイルしてサーバー・スタブ、Oracle Tuxedo ATMIランタイム、およびTxRPCランタイムとリンクし実行可能なサーバーを生成します。

図1-3 RPCクライアントの構築方法

図1-3については周囲のテキストで説明しています。

上の図はクライアントを作成するプロセスを示します。

  1. ステップ1で生成されたIDLファイルを用いて、IDLコンパイラ(tidl)を実行し、インタフェース・ヘッダー・ファイルとクライアント・スタブ・オブジェクト・ファイルを生成します。

  2. クライアント・アプリケーション・コード(client.c)を記述した後、buildclientを実行し、そのコードをコンパイルしてクライアント・スタブ、Oracle Tuxedo ATMIランタイム、およびTxRPCランタイムとリンクし実行可能なクライアントを生成します。

アプリケーション・クライアントおよびサーバーが作成されると、アプリケーションを構成および起動することができ、クライアントの実行が可能になります。詳細は、「アプリケーションの実行」で説明しています。