CORBAの初期化メソッドCORBA::ORB_init()を呼び出し、初期化処理を行います。結果として、ORBのオブジェクトリファレンスが返されます。このオブジェクトリファレンスは、以降で呼び出すORBインタフェースを使用する場合に指定します。
また、基本オブジェクトアダプタの初期化処理を行います。
サーバアプリケーションが実装するゲートウェイをORBに対して通知します。このため、以下の手順で処理を行います。
CORBA::ORB::resolve_initial_references()によりインプリメンテーションリポジトリのオブジェクトリファレンスを取り出します。メソッドのパラメタとしてCORBA_ORB_ObjectId_ImplementationRepositoryを指定します。
サーバアプリケーションのImplementationRepオブジェクトのオブジェクトリファレンスを求めるため、FJ::ImplementationRep::lookup_id()を発行します。
サーバアプリケーションが実装するゲートウェイを登録するために、CORBA::BOA::set_impl_dsi()を発行します。
boa->set_impl_dsi( boa, *env, (CORBA_DynamicImplementationRoutine_cpp)dsi );
サーバアプリケーションの初期化が完了すると、ORBに対してその旨を通知します。ORBは、この命令が発行された時点で、クライアントからの要求をサーバアプリケーションに伝えます。
ゲートウェイでは、以下に示す処理を行います。
メソッドの解析
パラメタの組立て
パラメタの解析
処理部の起動
復帰情報の設定
例外情報の設定
ゲートウェイの実装例を以下に示します。
static void dsi( CORBA::Object_ptr obj, CORBA::ServerRequest_ptr request, CORBA::Environment &ev ) { CORBA::RepositoryId dsi_op_name; try { // (1) メソッドの解析 dsi_op_name = request->op_name( ev ); if( strcmp( dsi_op_name, "calculate" ) == 0 ) { method_calculate( request ); } CORBA::string_free( dsi_op_name ); } // (5) 例外情報の設定 catch ( ODdemo::calculator::ZEROPARAM &_zeroparam ) { CORBA::Any *_any = new CORBA::Any( _tc_ODdemo_calculator_ZEROPARAM, &_zeroparam ); request->exception( _any, ev ); } catch ( CORBA::Exception e ){ // 例外発生時の処理を記述してください。 // 復帰情報あるいは例外情報を設定してください } return; } void method_calculate( CORBA::ServerRequest_ptr request ) throw( CORBA::Exception ) { try { // (2) パラメタの組立て // パラメタリストの生成 CORBA::NVList_ptr arg_list; orb->create_list( 2, arg_list, *env ); CORBA::Any p1, p2; CORBA::Long l; // パラメタ情報の登録 l = 0; p1 <<= l; arg_list->add_value( "a", p1, CORBA::ARG_IN, *env ); p2 <<= l; arg_list->add_value( "b", p2, CORBA::ARG_IN, *env ); // (3) パラメタの解析 request->params( arg_list, *env ); CORBA::NamedValue_ptr nvp1, nvp2; nvp1 = arg_list->item(0,*env); nvp2 = arg_list->item(1,*env); CORBA::Any *r1, *r2; r1 = nvp1->value(*env); r2 = nvp2->value(*env); CORBA::Long a,b; (*r1) >>= a; (*r2) >>= b; cout << " a = [" << a << "] b = [" << b << "]" << endl; if ( b == 0 ){ ODdemo::calculator::ZEROPARAM excep = ODdemo::calculator::ZEROPARAM(); throw( excep ); } // (4) 復帰情報の設定 ODdemo::calculator::result *res = new ODdemo::calculator::result(); res->add_result = a+b; res->subtract_result = a-b; res->multiple_result = a*b; res->divide_result = (CORBA::Float)a/b; CORBA::Any *tmp_any = new CORBA::Any; tmp_any->replace( _tc_ODdemo_calculator_result, (void *)res, CORBA_TRUE ); request->result( tmp_any, *env ); } catch ( ODdemo::calculator::ZEROPARAM &_zeroparam ) { throw( _zeroparam ); } catch( CORBA::Exception e ) { throw( e ); } }
(1)メソッドの解析
CORBA::ServerRequest::op_name()を発行して、メソッド名の解析を行います。
(2)パラメタの組立て
パラメタリストの生成
CORBA::ORB::create_list()メソッドにより、アプリケーションに渡すパラメタを格納するための領域を保持するリストオブジェクトを生成します。このとき、引数として何個のパラメタを格納するかを指定します。結果として、CORBA::NVListオブジェクトが返されます。
パラメタ情報の登録
CORBA::NVList::add_item()により、サーバアプリケーションに渡すパラメタをリストオブジェクトに設定します。パラメタとして、CORBA::NVListオブジェクトリファレンス、サーバアプリケーションのパラメタの名前、型、値および長さを設定します。
(3)パラメタの解析
CORBA::ServerRequest::params()を発行して、パラメタの解析を行います。この結果、アプリケーションに渡すパラメタ値が取得されます。
(4)復帰情報の設定
CORBA::ServerRequest::result()を発行して、復帰情報の設定を行います。
(5)例外情報の設定
CORBA::ServerRequest::exception()を発行して、例外情報の設定を行います。
サーバアプリケーションは、利用者等からの停止要求を受けた場合、クライアントからの要求を以降受け付けない旨をORBに対して通知します。ORBはこの通知を受けて、クライアントからの処理要求をサーバアプリケーションに伝えず、クライアントに例外を返します。
初期化処理として以下の処理を行います。
CORBA::ORB_init()によりORBオブジェクトを取得します。
RootPOAのオブジェクトリファレンスを取得します。
RootPOAから、Default Servantを使用するポリシで子POAを生成します。
ゲートウェイを実装したServantオブジェクトを生成し、Default Servantとして子POAに登録します。これによりクライアントからの要求に対して、Servant内に記述したinvoke()メソッドが起動されます。
Servantオブジェクトを設定したPOAに関連付けられたPOAManagerのインスタンスに対しactivate()メソッドを発行します。
ゲートウェイでは、以下に示す処理を行います。
メソッドの解析
パラメタの組立て
パラメタの解析
復帰情報の設定
例外情報の設定
ゲートウェイの実装例を以下に示します。
【ゲートウェイ実装例】
class DSIServant : public virtual PortableServer::DynamicImplementation { public: DSIServant(){ _rep_id = "IDL:ODdemo/calculator:1.0"; }; ~DSIServant(){}; CORBA::Boolean invoke( CORBA::ServerRequest_ptr sr, CORBA::Environment &env ) { try{ // (1)メソッド名の取得 char *_name = sr->op_name(); //メソッド名の解析 if( !strcmp( _name, "calculate" )){ // (2)パラメタリストの設定 //パラメタリストの作成 CORBA::NVList_ptr _list = NULL; orb->create_list( 2, _list ); //パラメタ情報の登録 CORBA::Any _p1, _p2; _p1 <<= (CORBA::Long)0; _p2 <<= (CORBA::Long)0; _list->add_value( "a", _p1, CORBA::ARG_IN ); _list->add_value( "b", _p2, CORBA::ARG_IN ); // (3)パラメタの解析 sr->params(_list); CORBA::Long _param1, _param2; *(_list->item(0)->value()) >>= _param1; *(_list->item(1)->value()) >>= _param2; //処理部の起動 UserServant *_sv = new UserServant(); ODdemo::calculator::result *_result = _sv->calculate( _param1, _param2, env ); // (4)復帰情報の設定 CORBA::Any *_res = new CORBA::Any(); _res->replace( _tc_ODdemo_calculator_result, (void*)_result, CORBA_TRUE ); sr->result(_res); _sv->servant_delete(); } CORBA::string_free(_name); } catch( ODdemo::calculator::ZEROPARAM *_zeroparam ) { // (5) 例外情報の設定 env.exception(_zeroparam); CORBA::Any *_any = new CORBA::Any( _tc_ODdemo_calculator_ZEROPARAM, _zeroparam ); sr->exception( _any, env ); return true; } catch( CORBA::Exception e ) { // 例外発生時の処理を記述してください。 // 復帰情報あるいは例外情報を設定してください } return true; }; // (6)実装が必要なメソッド CORBA::RepositoryId _primary_interface( const PortableServer::ObjectId &oid, PortableServer::POA_ptr poa, CORBA::Environment& env ) { return _rep_id; }; private: CORBA::RepositoryId _rep_id; }; //処理部 class UserServant : public virtual PortableServer::ServantBase { public: UserServant(){}; ~UserServant(){}; ODdemo::calculator::result *calculate( CORBA::Long a, CORBA::Long b, CORBA::Environment &env ) throw( CORBA::Exception ) { if( b == 0 ){ throw new ODdemo::calculator::ZEROPARAM(); } ODdemo::calculator::result *_result = new ODdemo::calculator::result(); _result->add_result = a + b; _result->subtract_result = a - b; _result->multiple_result = a * b; _result->divide_result = (CORBA::Float)(a / b); return _result; } };
ゲートウェイを実装するServantオブジェクトは、PortableServer::DynamicImplementationを継承するものとして作成します。また、クライアントからのリクエストに対して起動されるメソッドとしてinvoke()メソッドを実装します。起動の際、invoke()の引数としてServerRequestクラスのオブジェクト(上記例ではreq)が渡されます。
処理部では、ゲートウェイを実装するServantオブジェクト内で、そのServantに対してservant_delete()を発行するために、PortableServer::ServantBaseクラスを継承します。
【ゲートウェイServantの必須メソッド(1)】
CORBA::boolean invoke( CORBA::ServerRequest_ptr req )
(1)メソッドの取得と解析
渡されたServerRequestクラスに登録されているオペレーション名をCORBA::ServerRequest::op_name()メソッドにより取得します。
(2)パラメタの組立て
パラメタリストの生成
CORBA::ORB::create_list()メソッドにより、アプリケーションに渡すパラメタを格納するための領域を保持するリストオブジェクトを生成します。このとき、引数として何個のパラメタを格納するかを指定します。結果として、CORBA::NVListオブジェクトが返されます(上記例では2)。
パラメタ情報の登録
CORBA::NVList::add_value()メソッドを使用して、パラメタ情報をNVListオブジェクトに格納します。引数として、パラメタ名、パラメタの値を格納するAny型オブジェクト、パラメタ種別(入出力)を設定します。
(3)パラメタの解析
生成したNVListオブジェクトを引数として、CORBA::ServerRequest::params()メソッドを呼び出します。この結果、アプリケーションに渡すパラメタ値が取得されます。
(4)復帰情報の設定
CORBA::ServerRequest::result()メソッドを発行して復帰情報の設定を行います。
(5)例外情報の設定
CORBA::ServerRequest::exception()メソッドを発行し例外情報の設定を行います。
(6)その他実装が必要なメソッド
ゲートウェイを実装するServantは、OMG規約上_primary_interface()メソッドを実装しておく必要があります。上記の例のように、PortableServer::POAクラスのオブジェクト、PortableServer::ObjectIdオブジェクトを引数とし、インタフェースリポジトリID相当の文字列("IDL:xxx:1.0")を戻り値とする形式で実装します。引数の値をメソッド内部で扱う必要は特にありません。
【ゲートウェイServantの必須メソッド(2)】
virtual CORBA::RepositoryId _primary_interface( const PortableServer::ObjectId& oid, ); PortableServer::POA_ptr poa, CORBA::Environment& = CORBA::Environment()) throw( CORBA::Exception ) = 0;
POAでDSIを使用する場合は、RTTIをサポートするC++コンパイラを使用してください。
【Visual C++の場合】
「プロジェクトの設定」で、RTTIを使用するようにします。
【Makefileでnmakeを使用する場合】
/GRオプションを追加してください。
動的スケルトンインタフェースを使用して動的にパラメタを作成する方法について説明します。
パラメタはCORBA::NVList::add_value()を使用して設定します。
inパラメタ
クライアントアプリケーションからinパラメタを受け取る場合、パラメタ領域の獲得/解放を行う必要はありません。add_value()は以下のように指定します。
CORBA::Any p1( ((*params)[0])->type, &i, CORBA_TRUE ); arg_list->add_value( name, /* IDLで指定したパラメタの名前を設定します */ p1, /* inで使用する値を設定したAny型を設定します */ CORBA::ARG_IN, /* CORBA::ARG_INを設定します */ *env );
outパラメタ
サーバアプリケーションの処理結果をoutパラメタで渡す場合、データ域獲得関数(CORBA::long_alloc()等)で領域を獲得し、そのポインタをadd_value()の第2パラメタに指定します。
CORBA::Any *p2 = new CORBA::Any( ((*params)[1])->type, &i, CORBA_TRUE ); arg_list->add_value( name, /* IDLで指定したパラメタの名前を設定します */ *p2, /* outの値を設定するAny型を設定します */ CORBA::ARG_OUT, /* CORBA::ARG_OUTを設定します */ *env );
獲得した領域は、CORBAサービス内でリクエスト復帰後に解放されます。
inoutパラメタ
クライアントアプリケーションからinoutパラメタを受け取る場合、パラメタ領域の獲得/解放を行う必要はありません。add_value()は以下のように指定します。
CORBA::Any *p3 = new CORBA::Any(( (*params)[2])->type, &i, CORBA_TRUE ); arg_list->add_value( name, /* IDLで指定したパラメタの名前を設定します */ *p3, /* inoutの値を設定するAny型を設定します */ CORBA::ARG_INOUT, /* CORBA::ARG_INOUTを設定します */ *env );
サーバアプリケーションの処理結果をinoutでクライアントアプリケーションに渡す場合、以下のようにします。
CORBA::ServerRequest::params()で通知されたパラメタ領域に値を設定します。
CORBA::ServerRequest::params()で通知されたパラメタ領域を、CORBA::free()でいったん解放した後、データ域獲得関数(CORBA::string_alloc()等)で領域を獲得し、そのポインタを再設定します。新しいデータをその領域に設定します。
inoutパラメタとして使用した領域は、リクエスト復帰後にスケルトンで解放されます。
復帰パラメタ
サーバアプリケーションの処理結果を復帰パラメタ渡す場合、データ域獲得関数(CORBA::long_alloc()等)で領域を獲得します。