目次 前 次 PDF


動的起動インタフェースの使い方

動的起動インタフェースの使い方
このトピックには次の項が含まれます:
このトピックの情報はCORBA C++クライアント・アプリケーションに適用されます。
呼出し方式とDIIの概要は、「静的起動と動的起動」を参照してください。
このトピックで説明するCORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
注意:
サード・パーティのCORBA Java ORBのテクニカル・サポートは、各ベンダーによって提供されます。Oracle Tuxedoでは、サード・パーティのCORBA Java ORBに関する技術的なサポートやマニュアルは提供していません。
DIIの使用
CORBAクライアント・アプリケーションからリクエストを送信する際、静的起動と動的起動を使い分けることには、それ相応の理由があります。同じCORBAクライアント・アプリケーションで両方の呼出し方式を使用する必要がある場合もあります。呼出し方式を選択するには、DIIの長所と短所を理解しておく必要があります。
静的起動と動的起動の大きな違いの1つは、どちらも同期一方向通信をサポートしているのに対し、動的起動だけが遅延同期通信をサポートしているという点です。
同期通信では、CORBAクライアント・アプリケーションはリクエストを送信し、レスポンスを取得するまで待機します。レスポンスを待っている間、CORBAクライアント・アプリケーションは他の作業を実行できません。遅延同期通信では、CORBAクライアント・アプリケーションはリクエストを送信し、他の作業を自由に実行できます。CORBAクライアント・アプリケーションは、リクエストが完了したかどうかを定期的にチェックし、完了した場合は、そのリクエストの結果を利用します。
さらに、DIIを使用すると、CORBAクライアント・アプリケーションは、自身が記述された時点で未知であったCORBAオブジェクト型のメソッドを呼び出すことができます。これは、静的起動とは対照的です。静的起動では、CORBAクライアント・アプリケーションには呼び出すCORBAオブジェクトの各型に対するクライアント・スタブが含まれている必要があります。ただし、DIIでは、コードでクライアント・スタブの作業を実行する必要があるため、プログラミングが難しくなります。
CORBAクライアント・アプリケーションは、DIIを使用してより高いパフォーマンスを実現できます。たとえば、CORBAクライアント・アプリケーションは複数の遅延同期リクエストを同時に送信し、それらの完了を処理できます。リクエストが異なるサーバー・アプリケーションに送信された場合、この処理を並列に行うことができます。同期クライアント・スタブを使用している場合は、こうした処理を行うことができません。
注意:
DIIは、単なるCORBAクライアント・アプリケーションへのインタフェースです。CORBAサーバー・アプリケーションからは、静的起動と動的起動はまったく同じに見えます。
DIIの概念
多くの場合、DIIはあるタスクを達成するための複数の方法を提供し、これらの方法の間にはプログラミングの簡潔さとパフォーマンスのトレード・オフがあります。この項では、DIIの使い方を理解するために必要な高度な概念について説明します。このトピックの後半には、サンプル・コードなどの詳細を示します。
この項で説明する概念は次のとおりです。
リクエスト・オブジェクト
リクエスト・オブジェクトは、あるCORBAオブジェクトの1つのメソッドの1つの呼出しを表します。同じメソッドに対して2つの呼出しを行う場合、2つのリクエスト・オブジェクトを作成する必要があります。
メソッドを呼び出すには、そのメソッドが含まれているCORBAオブジェクトへのオブジェクト参照が必要です。オブジェクト参照を使用して、リクエスト・オブジェクトを作成し、そのリクエスト・オブジェクトに引数を指定し、リクエストを送信し、応答を待機して、リクエストの結果を取得します。
リクエスト・オブジェクトは、次の方法で作成できます。
CORBA::Object::_requestメンバー関数を使用します。
CORBA::Object::_requestメンバー関数を使用して、そのリクエストで呼び出すインタフェース名のみを指定する空のリクエスト・オブジェクト(get_course_detailsなど)を作成します。リクエスト・オブジェクトを作成したら、CORBAサーバー・アプリケーションに送信する前に引数を指定する必要があります(存在する場合)。呼び出すメソッドで必要な引数ごとに、CORBA::NVList::add_valueメンバー関数を呼び出します。
また、CORBA::Request::resultメンバー関数を使用して、リクエストの結果の型を指定する必要があります。パフォーマンス上の理由から、Object Request Brokers (ORB)間で交換されるメッセージには型情報は含まれません。結果の型のプレース・ホルダーを指定することによって、応答から結果を適切に抽出するために必要な情報をORBに提供します。同様に、呼び出すメソッドによって例外が発生する可能性がある場合、リクエスト・オブジェクトを送信する前に例外用のプレース・ホルダーを追加する必要があります。
CORBA::Object::_create_requestメンバー関数を使用します。
CORBA::Object:: _create_requestメンバー関数を使用してリクエスト・オブジェクトを作成する場合、そのリクエストを行うために必要なすべての引数を受け渡し、その結果の型とそのリクエストが返す可能性のあるユーザー例外を指定します。このメンバー関数を使用することで、空のNVListを作成し、一度に1つの引数をNVListに追加し、リクエスト・オブジェクトを作成して、完成したNVListをそのリクエストに引数として受け渡します。CORBA::Object::_create_request メンバー関数には、パフォーマンス上のメリットがあります。複数のオブジェクトの同じオブジェクトを呼び出す場合、これらの引数を複数のCORBA::ORB::_create_request呼出しで再利用できます。
CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
リクエスト送信オプション
リクエスト・オブジェクトを作成し、引数、結果の型および例外の型を追加したら、そのリクエストをCORBAオブジェクトに送信します。リクエストを送信するには、次のように複数の方法があります。
最も単純な方法は、CORBA::Request::invokeメンバー関数を呼び出すことです。この関数は、応答メッセージを取得するまでブロックします。
より複雑だが、ブロックが行われない方法は、CORBA::Request::send_deferredメンバー関数を使用することです。
複数のCORBAリクエストを並列に呼び出す場合は、CORBA::ORB::send_multiple_requests_deferredメンバー関数を使用します。これは、リクエスト・オブジェクトのシーケンスを取ります。
複数の一方向メソッドを並列に呼び出す場合は、ORBのCORBA::ORB::send_multiple_requests_onewayメンバー関数を使用します。
注意:
CORBA::Request::send_deferredメンバー関数を使用する場合、ターゲット・オブジェクトが呼出しを発行するCORBAクライアント・アプリケーションと同じアドレス空間に存在するときには、リクエスト・オブジェクトの呼出しは同期的に動作します。この動作の結果、CosTransaction::Current::suspend操作を呼び出しても、CORBA::BAD_IN_ORDER例外は発生しません。トランザクションが完了したからです。
CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
リクエスト結果受信オプション
呼出しメソッドを使用してリクエストを送信する場合、結果を取得する方法は1つのみです。その方法とは、リクエスト・オブジェクトのCORBA::Request::envメンバー関数を使用して例外をチェックし、例外が存在しない場合はCORBA::Request::resultメンバー関数を使用してリクエスト・オブジェクトからNVListを抽出することです。
遅延同期メソッドを使用してリクエストを送信した場合、次のいずれかのメンバー関数を使用して結果を取得できます。
このメンバー関数は、リクエストが完了し、処理の準備ができているかどうかを調べます。このメンバー関数はブロックしません。リクエストを処理できる場合、CORBAクライアント・アプリケーションはget_response()またはget_next_response()メンバー関数を使用してレスポンスを処理する必要があります。このメンバー関数は、レスポンスの処理順序を考慮しない場合、CORBAクライアント・アプリケーションが特定のレスポンスを待つ間にほかのリクエストを処理する場合、またはタイムアウトを設定する場合に使用します。
このメンバー関数は、未処理のリクエストのレスポンスが処理できる状態にあるかどうかを示します。処理できる場合、CORBAクライアント・アプリケーションはget_response()またはget_next_response()メンバー関数を使用してレスポンスを処理する必要があります。このメンバー関数は、リクエストの処理順序が重要ではなく、CORBAクライアント・アプリケーションが特定のレスポンスを待つ間にほかのリクエストを処理する場合に使用します。
このメンバー関数は、特定のリクエストに対するレスポンスが完了して処理されるまでブロックします。このメンバー関数は、未処理のリクエストを特定の順序で処理する場合に使用します。
このメンバー関数は、未処理のリクエストに対するレスポンスが完了して処理されるまでブロックします。このメンバー関数は、リクエストの処理順序が重要でない場合に使用します。
CORBA::Request::send_onewayメンバー関数を使用する場合、結果は存在しません。
CORBAメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
DIIの開発プロセスのサマリー
クライアント・アプリケーションでのDIIの使用手順を表3-1に示します。
 
以降の項では、これらのステップについて詳しく説明し、C++のサンプル・コードを示します。
ステップ1: CORBAインタフェースのインタフェース・リポジトリへのロード
DIIを使用するCORBAクライアント・アプリケーションを作成する前に、CORBAオブジェクトのインタフェースをインタフェース・リポジトリにロードしておく必要があります。CORBAオブジェクトのインタフェースがインタフェース・リポジトリにロードされていない場合、Oracle Application Builderにはそれらが表示されません。目的のCORBAインタフェースが「サービス」ウィンドウに表示されない場合は、idl2irコマンドを使用して、CORBAオブジェクトを定義するOMG IDLをインタフェース・リポジトリにロードします。idl2irコマンドの構文を表3-2に示します。
idl2ir [-f repositoryfile.idl] file.idl
 
-f repositoryfile
idl2irコマンドの詳細は、『Oracle Tuxedoコマンド・リファレンス』を参照してください。
ステップ2: CORBAオブジェクトのオブジェクト参照の取得
Bootstrapオブジェクトを使用して、FactoryFinderオブジェクトを取得します。次に、FactoryFinderオブジェクトを使用して、DIIリクエストからアクセスするCORBAオブジェクトのファクトリを取得します。BoostrapオブジェクトとFactoryFinderオブジェクトを使用してファクトリを取得する例は、「ステップ4: CORBAクライアント・アプリケーションの記述」を参照してください。
ステップ3:リクエスト・オブジェクトの作成
CORBAクライアント・アプリケーションがCORBAオブジェクトのメソッドを呼び出す場合、そのメソッド呼出しのためのリクエストを作成します。このリクエストはバッファに書き込まれ、CORBAサーバー・アプリケーションに送信されます。CORBAクライアント・アプリケーションがクライアント・スタブを使用する場合、この処理は透過的に発生します。DIIを使用するクライアント・アプリケーションは、リクエスト・オブジェクトを作成し、そのリクエストを送信する必要があります。
CORBA::Object::_requestメンバー関数の使い方
次のC++のサンプル・コードに、CORBA::Object::_requestメンバー関数の使い方を示します。
Boolean aResult;
CORBA::ULong long1 = 42;
CORBA::Any in_arg1;
CORBA::Any &in_arg1_ref = in_arg1;

in_arg1 <<= long1;
// Create the request using the short form
Request_ptr reqp = anObj->_request(“anOp”);
// Use the argument manipulation helper functions
reqp->add_in_arg() <<= in_arg1_ref;
// We want a boolean result
reqp->set_return_type(_tc_boolean);
// Provide some place for the result
CORBA::Any::from_boolean boolean_return_in(aResult);
reqp->return_value() <<= boolean_return_in;
// Do the invoke
reqp->invoke();
// No error, so get the return value
CORBA::Any::to_boolean boolean_return_out(aResult);
reqp->return_value() >>= boolean_return_out;
CORBA::Object::create_requestメンバー関数の使い方
CORBA::Object::create_requestメンバー関数を使用してリクエスト・オブジェクトを作成する場合、空のNVListを作成し、そのNVListに引数を1つずつ追加します。次に、リクエスト・オブジェクトを作成し、完成したNVListを引数としてそのリクエストに受け渡します。
リクエスト・オブジェクトの引数の設定
リクエスト・オブジェクトの引数は、名前付き/値オブジェクトを格納するNVListオブジェクトで表されます。このリスト内のオブジェクトの追加、削除、問合せを行うためのメソッドが用意されています。CORBA::NVListの詳細は、『CORBAプログラミング・リファレンス』を参照してください。
CORBA::NamedValueメンバー関数による入力引数と出力引数の設定
CORBA::NamedValueメンバー関数は、リクエストの入力引数と出力引数を表すために使用する名前付き/値オブジェクトを指定します。名前付き/値オブジェクトは、リクエスト・オブジェクトの引数として使用されます。また、CORBA::NamedValueのペアは、CORBAクライアント・アプリケーションに返されるリクエストの結果を表すためにも使用されます。名前付き/値オブジェクトの名前プロパティは文字列で、値プロパティはCORBA Anyによって表されます。
CORBA::NamedValueメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
CORBA::Object::create_requestメンバー関数の使用例
次のC++のサンプル・コードに、CORBA::Object::create_requestメンバー関数の使い方を示します。
CORBA::Request_ptr reqp;
CORBA::Context_ptr ctx;
CORBA::NamedValue_ptr boolean_resultp = 0;
Boolean boolean_result;
CORBA::Any boolean_result_any(CORBA::_tc_boolean, & boolean_result);
CORBA::NVList_ptr arg_list = 0;
CORBA::Any arg;
// Get the default context
orbp->get_default_context(ctx);
// Create the named value pair for the result
(void) orbp->create_named_value(boolean_resultp);
CORBA::Any *tmpany = boolean_resultp->value();
*tmpany = boolean_result_any;

arg.replace(CORBA::_tc_long, &long_arg, CORBA_FALSE)
// Create the NVList
orbp->create_list(1, arg_list);

// Add an IN argument to the list
arg_list->add_value(“arg1”, arg, CORBA::ARG_IN);

// Create the request using the long form
anObj->_create_request (ctx,
“anOp”,
arg_list,
boolean_resultp,
reqp,
CORBA::VALIDATE_REQUEST );
// Do the invoke
reqp->invoke();

CORBA::NamedValue_ptr result_namedvalue;
Boolean aResult;
CORBA::Any *result_any;
// Get the result
result_namedvalue = reqp->result();
result_any = result_namedvalue->value();
// Extract the Boolean from the any
*result_any >>= aResult;
ステップ4: DIIリクエストの送信と結果の取得
リクエストは、使用する通信の方式に応じて複数の方法で呼び出すことができます。この項では、CORBAメンバー関数を使用してリクエストの送信と結果の取得を行う方法について説明します。
同期リクエスト
同期通信を行う場合、CORBA::Request::invokeメンバー関数はリクエストを送信し、そのレスポンスがCORBAクライアント・アプリケーションに返されるまで待機します。CORBA::Request::resultメンバー関数は、戻り値を表す名前付き/値オブジェクトの参照を返すために使用します。結果を取得したら、リクエストに格納されているNVListから値を読み出します。
遅延同期リクエスト
リクエストの送信用として、非ブロッキング・メンバー関数のCORBA::Request::send_deferredも用意されています。このメンバー関数を使用すると、CORBAクライアント・アプリケーションはリクエストを送信し、CORBA::Request::poll_response メンバー関数を使用してレスポンスが利用可能であるかどうかを調べることができます。CORBA::Request::get_responseメンバー関数は、レスポンスが利用可能になるまでブロックします。
次のサンプル・コードに、CORBA::Request::send_deferredCORBA::Request::poll_responseおよびCORBA::Request::get_responseメンバー関数の使い方を示します。
request->send_deferred ();

if (poll)
{
for ( int k = 0 ; k < 10 ; k++ )
{
CORBA::Boolean done = request->poll_response();
if ( done )
break;
}
}
request->get_response();
一方向リクエスト
一方向リクエストを送信するには、CORBA::Request::send_onewayメンバー関数を使用します。一方向リクエストでは、CORBAサーバー・アプリケーションからレスポンスが返されません。CORBA::Request::send_onewayメンバー関数の詳細は、『CORBAプログラミング・リファレンス』を参照してください。
次のサンプル・コードに、CORBA::Request::send_onewayメンバー関数の使い方を示します。
request->send_oneway();
複数のリクエスト
CORBA::Request::send_multiple_requests_deferredメンバー関数を使用してリクエスト・オブジェクトのシーケンスを送信する場合、CORBA::ORB::poll_responseCORBA::ORB::poll_next_response、CORBA::ORB::get_responseおよびCORBA::ORB::get_next_responseメンバー関数を使用すると、CORBAサーバー・アプリケーションが各リクエストに対して送信するレスポンスを取得できます。
CORBA::ORB::poll_responseメンバー関数とCORBA::ORB::poll_next_responseメンバー関数を使用すると、CORBAサーバー・アプリケーションからレスポンスを取得したかどうかを調べることができます。これらのメンバー関数は、少なくとも1つのレスポンスが利用可能な場合は1を返し、利用可能なレスポンスが存在しない場合は0を返します。
CORBA::ORB::get_responseメンバー関数とCORBA::ORB::get_next_responseメンバー関数を使用すると、レスポンスを取得できます。利用可能なレスポンスが存在しない場合、これらのメンバー関数はレスポンスを取得するまでブロックします。CORBAクライアント・アプリケーションがブロックしないようにする場合は、最初にCORBA::ORB::poll_next_responseメンバー関数を使用してレスポンスが利用可能かどうかを調べてから、CORBA::ORB::get_next_responseメソッドを使用してその結果を取得します。
また、CORBA::Request::send_multiple_requests_onewayメンバー関数を使用すると、複数の一方向リクエストを送信できます。
次のサンプル・コードに、CORBA::Request::send_multiple_requests_deferredCORBA::Request::poll_next_responseおよびCORBA::Request::get_next_responseメンバー関数の使い方を示します。
CORBA::Context_ptr ctx;
CORBA::Request_ptr requests[2];
CORBA::Request_ptr request;
CORBA::NVList_ptr arg_list1, arg_list2;
CORBA::ULong i, nreq;
CORBA::Long arg1 = 1;
Boolean aResult1 = CORBA_FALSE;
Boolean expected_aResult1 = CORBA_TRUE;
CORBA::Long arg2 = 3;
Boolean aResult2 = CORBA_FALSE;
Boolean expected_aResult2 = CORBA_TRUE

try
{
orbp->get_default_context(ctx);

populate_arg_list ( &arg_list1, &arg1, &aResult1 );

nreq = 0;

anObj->_create_request ( ctx,
“Multiply”,
arg_list1,
0,
requests[nreq++],
0);

populate_arg_list ( &arg_list2, &arg2, &aResult2 );

anObj->_create_request ( ctx,
“Multiply”,
arg_list2,
0,
requests[nreq++],
0 );

// Declare a request sequence variable...
CORBA::ORB::RequestSeq rseq ( nreq, nreq, requests, CORBA_FALSE );

orbp->send_multiple_requests_deferred ( rseq );
for ( i = 0 ; i < nreq ; i++ )
{
requests[i]->get_response();
}
// Now check the results
if ( aResult1 != expected_aResult1 )
{
cout << “aResult1=” << aResult1 << “ different than expected: “ <<
expected_aResult1;
}
if ( aResult2 != expected_aResult2 )
{
cout << “aResult2=” << aResult2 << “ different than expected: “ <<
expected_aResult2;
}
aResult1 = CORBA_FALSE;
aResult2 = CORBA_FALSE;
// Using the same argument lists, multiply the numbers again.
// This time we intend to poll for response...

orbp->send_multiple_requests_deferred ( rseq );

// Now poll for response...
for ( i = 0 ; i < nreq ; i++ )
{
// We will randomly poll maximum 10 times...
for ( int j = 0 ; j < 10 ; j++ )
{
CORBA::Boolean done = requests[i]->poll_response();

if ( done ) break;
}
}
// Now actually get the response...
for ( i = 0 ; i < nreq ; i++ )
{
requests[i]->get_response();
}
// Now check the results
if ( aResult1 != expected_aResult1 )
{
cout << “aResult1=” << aResult1 << “ different than expected: “ <<
expected_aResult1
}
if ( aResult2 != expected_aResult2 )
{
cout << “aResult2=” << aResult2 << “ different than expected: “ <<
expected_aResult2;
}
aResult1 = CORBA_FALSE;
aResult2 = CORBA_FALSE;
// Using the same argument lists, multiply the numbers again.
// Call get_next_response, and WAIT for a response.
orbp->send_multiple_requests_deferred ( rseq );

// Poll until we get a response and then use get_next_response get it...
for ( i = 0 ; i < nreq ; i++ )
{
CORBA::Boolean res = 0;

while ( ! res )
{
res = orbp->poll_next_response();
}
orbp->get_next_response(request);
CORBA::release(request);
}
// Now check the results
if ( aResult1 != expected_aResult1 )
{
cout << “aResult1=” << aResult1 << “ different than expected: “ <<
expected_aResult1;
}
if ( aResult2 != expected_aResult2 )
{
cout << “aResult2=” << aResult2 << “ different than expected: “ <<
expected_aResult2;
}
 
static void populate_arg_list (
CORBA::NVList_ptr ArgList,
CORBA::Long * Arg1,
CORBA::Long * Result )
{
CORBA::Any any_arg1;
CORBA::Any any_result;

(* ArgList) = 0;
orbp->create_list(3, *ArgList);

any_arg1 <<= *Arg1;
any_result.replace(CORBA::_tc_boolean, Result, CORBA_FALSE);
(*ArgList)->add_value(“arg1”, any_arg1, CORBA::ARG_IN);
(*ArgList)->add_value(“result”, any_result, CORBA::ARG_OUT);

return;
}
ステップ5:リクエストの削除
リクエストが正常に完了したことが通知されたら、既存のリクエストを削除するか、または次の呼出しでその一部を再利用するかを決定する必要があります。
リクエスト全体を削除するには、削除するリクエストに対してCORBA::Release(request)メンバー関数を使用します。この操作により、リクエストに関連するすべてのメモリーが解放されます。遅延同期通信を使用して発行されたリクエストを削除する場合、そのリクエストが完了していないときはそのリクエストが取り消されされます。
ステップ6: DIIでのインタフェース・リポジトリの使い方
CORBAクライアント・アプリケーションは、ビルド時に未知であったオブジェクトのリクエストを作成、設定および送信できます。そのために、CORBAクライアント・アプリケーションはインタフェース・リポジトリを使用して、リクエストを作成および設定するために必要な情報を取得します。CORBAクライアント・アプリケーションは、そのインタフェースのクライアント・スタブを持っていないので、DIIを使用してリクエストを送信します。
この手法は未知の型のCORBAオブジェクトの操作を呼び出す場合に役立ちますが、インタフェース・リポジトリとの対話によるオーバーヘッドのため、パフォーマンスが問題となります。このタイプのDIIリクエストは、オブジェクトを参照するCORBAクライアント・アプリケーションを作成する場合か、管理ツールであるCORBAクライアント・アプリケーションを作成する場合に使用を検討します。
DIIリクエストでインタフェース・リポジトリを使用するための手順は次のとおりです。
1.
CORBA.hORB_INCLUDE_REPOSITORYを、Oracle Tuxedoシステム内でのインタフェース・リポジトリ・ファイルの格納場所に設定します。
2.
3.
CORBA::Object::_get_interfaceメンバー関数を使用して、目的のCORBAオブジェクトを実装するCORBAサーバー・アプリケーションと通信します。
4.
CORBA::InterfaceDef_ptrを使用して、インタフェース・リポジトリに格納されているCORBAインタフェースの定義を取得します。
5.
FullInterfaceDescription操作で、目的の操作用のOperationDescriptionを検索します。
6.
OperationDescriptionからリポジトリIDを取得します。
7.
OperationDescriptionで返されたリポジトリIDを使用してCORBA::Repository::lookup_idを呼び出して、インタフェース・リポジトリ内のOperationDefを検索します。この呼出しにより、包含オブジェクトが返されます。
8.
包含オブジェクトをOperationDefにナロー変換します。
9.
OperationDef引数とCORBA::ORB::create_operation_listメンバー関数を使用して、操作の引数リストを作成します。
10.
11.
 

Copyright ©1994, 2017,Oracle and/or its affiliates. All rights reserved