動的スケルトンインタフェース (DSI: Dynamic Skeleton Interface) |
IDLコンパイラが自動生成するスケルトンを用いた静的な起動では、各オペレーションに対し1対1で対応した固定された処理が行われます。これに対し、動的スケルトンインタフェース(DSI)ではインタフェース定義情報を静的には持たずに任意のオブジェクトを呼び出す汎用的なオブジェクトインプリメンテーションを作成することができます。通常、サーバアプリケーションを作成するには静的なスケルトンで十分です。動的スケルトンインタフェース(DSI)が必要となるのは任意のオブジェクトにリクエストを渡すためのブリッジなど特殊な場合です。
動的起動インタフェース(DSI)を利用するには、PortableServer::DynamicImplementationクラスを継承し、決められたメソッドの実装部を記述する必要があります。
4.4.2.2. PortableServer::Servantクラス |
PortableServer::ServantはC++マッピングでは以下のとおりに定義されています。
// C++ namespace PortableServer { ... typedef ServantBase* Servant; };
PortableServer::ServantBaseは実装オブジェクトを定義するための抽象クラスです。PortableServer::ServantBaseクラスがもつ下記のメソッドは、ユーザもしくはコンパイラによってオーバーライドされます。
なお、PortableServer::Servantや継承されたクラスを使い、直接PortableServer::ServantBaseを使うことはありません。
_default_POA | デフォルトPOAを取り出す |
__version | 実装オブジェクトのバージョンを得る |
__lifetime | 実装オブジェクトのライフタイムを得る |
__createtime | 実装オブジェクトの生成時刻を得る |
__status | 実装オブジェクトのステータスを得る |
__stop | 実装オブジェクトが動作するプロセスの終了 |
4.4.2.17. PortableServer::DynamicImplementationクラス |
PortableServer::DynamicImplementationはORBからサーバアプリケーションを呼び出す入口のための抽象クラスで、PortableServer::ServantBaseクラスを継承しています。DSIを使ったサーバアプリケーションの開発者は、このクラスを継承したクラスを実装します。
_this | 呼び出し対象のオブジェクトを取り出す |
invoke | ORBからサーバアプリケーションへの入口 |
_primary_interface | 呼び出し対象のインタフェースのリポジトリIDを取り出す |
このほかにPortableServer::Servantで示した各メンバもオーバーライドします。
4.4.1.9. CORBA::ServerRequestクラス |
CORBA::ServerRequestは、ORBとサーバアプリケーションの間で、クライアントが呼び出したオペレーションの引数や戻り値などをやり取りするためのクラスです。このインスタンスはORB側で作られ、PortableServer::DynamicImplementation::invokeの引数としてサーバアプリケーションに渡されます。サーバアプリケーションは、ここからオペレーションの名前、コンテキスト、引数リストを取り出したり、オペレーションの戻り値や例外をセットして、ORBに渡したりします。
operation | オペレーション名を得る |
ctx | コンテキストを得る |
arguments | 引数リストを得る |
set_result | 戻り値をセットする |
set_exception | 例外をセットする |
PortableServer::Servant::_default_POA - デフォルトPOAを取り出す
#include <orb.h> virtual PortableServer::POA_ptr PortableServer::Servant::_default_POA( CORBA::Environment& env = Ob_default_environment() );
デフォルトPOAを取り出します。
通常、このメソッドはルートPOAを返します。このメソッドをオーバーライドすることでルートPOAとは異なるPOAを返すこともできます。
デフォルトPOAを返します。
CORBA標準例外がthrowされます。
PortableServer::Servant::__version
- 実装オブジェクトのバージョンを得る
#include <orb.h> virtual char* PortableServer::Servant::__version(CORBA::Environment& env);
実装オブジェクトのバージョンを返します。
__version関数は、クライアント側がCORBA::Object::__version関数を呼び出したとき、実際に結果を返す関数です。__version関数のデフォルト動作は"1.0"文字列を返すのみですが、オブジェクト実装クラスでオーバライドすることにより、動作を変えることができます。
envは、関数を呼び出した後、例外の有無を調べるために指定します(オプション)。
バージョン情報を文字列で返します。戻り値は自動的に解放されます。
CORBA標準例外がthrowされます。
PortableServer::Servant::__lifetime
- 実装オブジェクトのライフタイムを得る
PortableServer::Servant::__createtime
- 実装オブジェクトの生成時刻を得る
#include <orb.h> virtual CORBA::ULong PortableServer::Servant::__lifetime( CORBA::Environment& env ); virtual CORBA::ULong PortableServer::Servant::__createtime( CORBA::Environment& env );
__lifetime関数は実装オブジェクトのライフタイムを返します。
__createtime関数は実装オブジェクトの生成時刻を返します。
envは、関数を呼び出した後、例外の有無を調べるために指定します(オプション)。
__lifetime関数と__createtime関数は、クライアント側がCORBA::Object::__lifetime関数、CORBA::Object::__createtime関数を呼び出したとき、実際に結果を返す関数です。__createtime関数のデフォルト動作はC++オブジェクトが生成されたときの時刻を返します。__lifetime関数のデフォルト動作は「現在の時刻 - __createtimeの結果」を返します。それぞれの関数をオブジェクト実装クラスでオーバライドすることにより、動作を変えることができます。
秒単位で計測した時間をCORBA::ULong型で返します。
生成した時刻は1970年1月1日00:00:00 UTCからの時間を返します。
CORBA標準例外がthrowされます。
CORBA::Object::__lifetime, CORBA::Object::__createtime
PortableServer::Servant::__status
- オブジェクトのステータスを得る
#include <orb.h> virtual CORBA::ULong PortableServer::Servant::__status( CORBA::Environment& env );
実装オブジェクトのステータスを返します。
__status関数はクライアント側がCORBA::Object::__status関数を呼び出したとき、実際に結果を返す関数です。__status関数のデフォルト動作は0の値を返すのみですが、オブジェクト実装クラスでオーバライドすることにより、動作を変えることができます。
ステータスの値をCORBA::ULong型で返します。
CORBA標準例外がthrowされます。
PortableServer::Servant::__stop
- 実装オブジェクトが動作するプロセスの終了
#include <orb.h> virtual void PortableServer::Servant::__stop(CORBA::Environment& env);
クライアントからの呼び出しによって実装オブジェクトが動作するプロセスを終了させたいときに、このオペレーションを使います。
__stop関数は、クライアント側がCORBA::Object::__stop関数を呼び出したとき、実際の処理をする関数です。
本来、__stop関数は何もしません。しかし、オブジェクト実装クラスで__stop関数をオーバライドすることにより、動作を変えることができます。例えば、CORBA::ORB::run関数の処理から抜けるようにするにはオーバーライドした関数内でCORBA::ORB::shutdown関数を呼び出します。
envは、関数を呼び出した後、例外の有無を調べるために指定します(オプション)。
ありません。
CORBA標準例外がthrowされます。
PortableServer::DynamicImplementation::_this
- 呼び出し対象のオブジェクトを取り出す
#include <orb.h> CORBA::Object_ptr PortableServer::DynamicImplementation::_this( CORBA::Environment& env = Ob_default_environment() );
このメソッドは、呼び出し対象のオブジェクトがDSIサーバントと対応付けられているとき、その対象オブジェクトのオブジェクトリファレンスをCORBA::Object_ptr型で返します。
DSIサーバントは複数の異なる型のCORBAオブジェクトを実現することができるため、戻り値にインタフェース固有の型では返しません。
呼び出しの対象となっているオブジェクトをCORBA::Object_ptr型で返します。
DSIサーバントのとき、かつ、invoke関数の処理開始から終了の間以外のとき、または呼び出し対象のオブジェクトがDSIサーバントと対応付けられていないときに呼び出すと、PortableServer::POA::WrongPolicy例外がthrowされます。それ以外はCORBA標準例外がthrowされます。
PortableServer::DynamicImplementation::invoke,
PortableServer::DynamicImplementation::_primary_interface,
[ アプリケーション開発ガイド(CORBA) > 1. CORBA アプリケーション > 1.2. プログラミング・開発ガイド > 1.2.2. Object Broker > 1.2.2.6. Object Broker C++の機能 > Dynamic Skeleton Interface (DSI)]
IDLコンパイラが生成したスケルトンクラスは、_thisメソッドをオーバーライドし、インタフェース固有の型("インタフェース名"_ptr)で返します。
PortableServer::DynamicImplementation::invoke
- ORBからサーバアプリケーションへの入口
#include <orb.h> virtual void PortableServer::DynamicImplementation::invoke( CORBA::ServerRequest_ptr request, CORBA::Environment& env );
クライアントがオペレーションを呼び出したとき、ORBはサーバアプリケーションを呼び出します。そのときPOAから呼び出されるのがinvokeです。サーバアプリケーション開発者は、PortableServer::DynamicImplementationを継承した実装クラスを作成します。invokeの典型的な実装は次のとおりです。
(例)
// IDL enum T1 { a, b }; struct T2 { long l; } exception exc{}; interface foo { T2 op(in T1 arg) raises (exc); }; // C++(派生クラスの実装) class fooDynImpl : PortableServer::DynamicImplementation { public: void invoke(CORBA::ServerRequest_ptr, CORBA::Environment&); T2 op1(const T1 arg); }; void fooDyImpl::invoke(CORBA::ServerRequest_ptr request, CORBA::Environment&) { try { //どのオペレーションが呼ばれたのか調べる const char* op_name = request->operation(); if (strcmp(op_name, "op1")==0) { //op1メソッドが呼ばれたとき CORBA::ORB_var orb = ... // ORB疑似オブジェクトを取得 //引数情報を組み立てる CORBA::NVList_ptr param; orb->create_list(1, param); T1 arg; CORBA::NamedValue_ptr nv = param->add(CORBA::ARG_IN); CORBA::Any* ap = nv->value(); ap <<= arg; request->arguments(param); // 引数リストを作成する // IN引数を取り出す CORBA::NamedValue_ptr nv = param->item(0); ap = nv->value() ap >>= arg; T2 ret = op(arg); // オペレーションの呼び出し // 戻り値をセットする ap = new CORBA::Any; *ap <<= ret; request->set_result(*ap); } ... } catch(CORBA::Exception& e) { // 例外をセットする CORBA::Any* ap = new CORBA::Any(_tc_exc, new exc, 1); request->set_exception(*ap); } }
ありません。
CORBA標準例外がthrowされます。
PortableServer::DynamicImplementation::_primary_interface,
PortableServer::DynamicImplementation::_this,
CORBA::ServerRequest::operation,
CORBA::ServerRequest::arguments,
CORBA::ServerRequest::set_result,
CORBA::ServerRequest::set_exception,
[ アプリケーション開発ガイド(CORBA) > 1. CORBA アプリケーション > 1.2. プログラミング・開発ガイド > 1.2.2. Object Broker > 1.2.2.6. Object Broker C++の機能 > Dynamic Skeleton Interface (DSI)]
PortableServer::DynamicImplementation::_primary_interface
- 呼び出し対象のインタフェースのリポジトリIDを取り出す
#include <orb.h> virtual CORBA::RepositoryId PortableServer::DynamicImplementation::_primary_interface( const PortableServer::ObjectId& oid, PortableServer::POA_ptr poa, CORBA::Environment& env );
oidとpoaの組み合わせに合致したインタフェースのリポジトリIDを取り出します。このメソッドは、POAが呼び出し時に、呼び出し対象のインタフェースを取り出すために呼び出します。サーバアプリケーション開発者は、このメソッドをオーバーライドする必要があります。サーバントが複数のインタフェースをサポートしているときは、適切なインタフェースのリポジトリIDを返すように実装します。
基底インタフェースのリポジトリIDが返ります。
CORBA標準例外がthrowされます。
PortableServer::DynamicImplementation::invoke,
PortableServer::DynamicImplementation::this,
[ アプリケーション開発ガイド(CORBA) > 1. CORBA アプリケーション > 1.2. プログラミング・開発ガイド > 1.2.2. Object Broker > 1.2.2.6. Object Broker C++の機能 > Dynamic Skeleton Interface (DSI)]
CORBA::ServerRequest::operation - オペレーション名を得る
#include <orb.h> const char* CORBA::ServerRequest::operation( CORBA::Environment& env = Ob_default_environment() ) const;
クライアントが呼び出したオペレーションおよび属性の名前を返します。オペレーション名はIDLで定義した名前で表現されます。属性名は、取り出しと設定とで表現する名前が異なります。取り出しの名前には"_get_"が、設定の名前には"_set_"がIDLで定義した名前の前につきます。
また、CORBA::Objectのオペレーションのうち、_get_interface、_get_implementation、_is_aはサーバにリクエストが渡ることがあります。これらの名前はそれぞれ、"_interface"、_implementation"、"_is_a"です。
オペレーション名を文字列で返します。
CORBA標準例外がthrowされます。
CORBA::ServerRequest::arguments,
CORBA::ServerRequest::set_result,
CORBA::ServerRequest::set_exception
戻り値を変更したり、削除してはいけません。
CORBA::ServerRequest::ctx - コンテキストを得る
#include <orb.h> CORBA::Context_ptr CORBA::ServerRequest::ctx( CORBA::Environment& env = Ob_default_environment() );
IDL定義でコンテキスト指定のあるオペレーションをクライアントが呼び出したとき、サーバアプリケーションは、PortableServer::DynamicImplementation::invoke内で、オペレーションの引数を取り出したあと、このメソッドを使ってCORBA::ServerRequestからコンテキストを取り出します。
このメソッドは1回だけ呼び出すことができます。2回以上呼び出した場合はCORBA::BAD_INV_ORDER例外がthrowされます。
また、CORBA::ServerRequest::argumentsを呼び出す前やCORBA::ServerRequest::set_result, CORBA::ServerRequest::set_exceptionを呼び出した後で呼び出した場合もCORBA::BAD_INV_ORDER例外がthrowされます。
コンテキストが返ります。
2回以上呼び出した場合や呼び出し順序が不正だった場合はCORBA::BAD_INV_ORDER例外がthrowされます。
CORBA::ServerRequest::operation,
CORBA::ServerRequest::arguments,
CORBA::ServerRequest::set_result,
CORBA::ServerRequest::set_exception
コンテキストもオペレーションのシグニチャの一部です。クライアント−サーバ間のシグニチャが一致しないときの動作は保証されません。
CORBA::ServerRequest::arguments - 引数リストを得る
#include <orb.h> void CORBA::ServerRequest::arguments( CORBA::NVList_ptr& parameters, CORBA::Environment& env = Ob_default_environment() );
本関数はparametersの引数情報をもとにCORBA::ServerRequestから引数を取り出します。
サーバアプリケーションは、parametersにあらかじめ引数のタイプコードとモードを設定しておきます。
引数がないときはparametersにヌル・ポインタを指定します。引数が複数あるときは、IDLオペレーション定義の左側から順に設定します。
argumentsを呼び出した後、parametersからINおよびINOUT引数の値を取り出します。そして、オペレーション実行後、parametersにINOUTおよびOUT引数の値を設定します。
(例) 例外処理は省略します
interface foo { void op(in long argin, out short argout); }; // C++ // invokeの実装例 // (fooDIRはPortableServer::DynamicImplementationクラスの派生クラス) void fooDIR::invoke(CORBA::ServerRequest_ptr sr, CORBA::Environment&) { // どのオペレーションが呼ばれたかを調べる const char* opname = sr->operation(); if (strcmp(opname, "op") == 0) { // op()が呼ばれたとき CORBA::ORB_var orb = ...; // CORBA::ORB疑似オブジェクトを取得 CORBA::Any* avar; CORBA::NamedValue_ptr nv; CORBA::Long argin; // IN引数 CORBA::Short argout; // OUT引数 CORBA::NVList_ptr params; // パラメータの入出力用 // 引数情報を組み立てます orb->create_list(2, params); nv = params->add(CORBA::ARG_IN); avar = nv->value(); *avar <<= argin; nv = params->add(CORBA::ARG_OUT); avar = nv->value(); *avar <<= argout; // 引数リストを取得します sr->arguments(params); // 引数リストからIN引数を取り出します nv = params->item(0); avar = nv->value(); *avar >>= argin; // オペレーションを呼び出します op(argin, argout); // 引数リストにOUT引数を設定します nv = params->item(1); avar = nv->value(); *avar <<= argout; } ... }
この関数は1回だけ呼び出すことができます。2回以上呼び出したときには、CORBA::BAD_INV_ORDER例外(minor() = EMinor_AlreadyCalled)がthrowされます。
また、CORBA::ServerRequest::set_exceptionメソッドを呼び出した後に、このメソッドを呼び出してもCORBA::BAD_INV_ORDER例外がthrowされます。
ありません。
2回以上呼び出したとき、もしくは、CORBA::ServerRequest::set_exceptionメソッドを呼び出した後に、このメソッドを呼び出したときはCORBA::BAD_INV_ORDER例外がthrowされます。
CORBA::ServerRequest::operation,
CORBA::ServerRequest::set_result,
CORBA::ServerRequest::set_exception,
クライアント−サーバ間のデータの型や数が一致しないときの動作は保証されません。
引数に渡したCORBA::NVListのメモリ領域を解放するのは、CORBA::ServerRequest側の役割です。
CORBA::ServerRequest::set_result - 戻り値をセットする
#include <orb.h> void CORBA::ServerRequest::set_result( const CORBA::Any& value, CORBA::Environment& env = Ob_default_environment() );
オペレーションの戻り値をCORBA::ServerRequestにセットします。
このメソッドは、CORBA::ServerRequest::argumentsメソッドを呼び出したあとに1回だけ呼び出します。また、CORBA::ServerRequest::set_exceptionを呼び出した後に呼んではいけません。呼び出す順序を間違えたり、2回以上呼び出したときには、CORBA::BAD_INV_ORDER例外がthrowされます。
(例) 例外処理は省略します
// IDL interface foo { string op(); }; // C++ // invokeの実装例(fooDIRはPortableServer::DynamicImplementationクラスの派生クラス) void fooDIR::invoke(CORBA::ServerRequest_ptr sr, CORBA::Environment&) { // どのオペレーションが呼ばれたかを調べる const char* opname = sr->operation(); if (strcmp(opname, "op") == 0) { // op()が呼ばれたとき CORBA::NVList_ptr dummy = 0; sr->arguments(dummy); // op()は引数がないのでヌル・ポインタで呼び出します CORBA::String_var ret = op(); // オペレーションを呼び出します // 戻り値をセットします CORBA::Any* v = new CORBA::Any; *v <<= (const char*)ret; sr->set_result(*v); } ... }
ありません。
呼び出す順序を間違えたり、2回以上呼び出したときには、CORBA::BAD_INV_ORDER例外がthrowされます。
CORBA::ServerRequest::operation,
CORBA::ServerRequest::arguments,
CORBA::ServerRequest::set_exception,
クライアント−サーバ間の戻り値の型が一致しないときの動作は保証されません。
引数に渡したCORBA::Anyのメモリ領域を解放するのは、CORBA::ServerRequest側の役割です。
CORBA::ServerRequest::set_exception - 例外をセットする
#include <orb.h> void CORBA::ServerRequest::set_exception( const CORBA::Any& value, CORBA::Enviornment& env = Ob_default_environment() );
オペレーションの結果例外が起きたとき、その例外をCORBA::ServerRequestにセットします。valueには例外を挿入したものを指定します。
この関数は、例外発生時に1回だけ呼び出します。2回以上呼び出したときには、CORBA::BAD_INV_ORDER例外(minor() = EMinor_AlreadyCalled)がthrowされます。また、valueに例外を挿入していないときには、CORBA::BAD_PARAM例外がthrowされます。
なお、例外が発生しなかったときは、この関数を呼び出す必要はありません。
(例)
// IDL exception exc {}; exception other_exc {}; interface foo { void op() raises (exc, other_exc); }; // C++ // invokeの実装例(fooDIRはPortableServer::DynamicImplementationクラスの派生クラス) void fooDIR::invoke(CORBA::ServerRequest_ptr sr, CORBA::Environment&) { try { // どのオペレーションが呼ばれたかを調べる const char* opname = sr->operation(); if (strcmp(opname, "op") == 0) { // op()が呼ばれたとき CORBA::NVList_ptr dummy = 0; sr->arguments(dummy); // op()は引数がないのでヌル・ポインタで呼び出します op(); // オペレーションを呼び出します } ... } catch (exc& e) { // exc例外をcatchしたとき // exc例外をセットします CORBA::Any* v = new CORBA::Any(_tc_exc, new exc(e), 1); sr->set_exception(*v); } catch (CORBA::Exception& e) { // その他の例外をcatchしたとき // other_exe例外をセットします CORBA::Any* v = new CORBA::Any(_tc_other_exc, new other_exc, 1); sr->set_exception(*v); } }
ありません。
CORBA標準例外がthrowされます。
CORBA::ServerRequest::operation,
CORBA::ServerRequest::arguments,
CORBA::ServerRequest::set_result,
例外もオペレーションのシグニチャの一部です。クライアント−サーバ間のシグニチャが一致しないときの動作は保証されません。
引数に渡したCORBA::Anyのメモリ領域を解放するのは、CORBA::ServerRequest側の役割です。