CORBAサーバントの生成
CORABサーバントを生成する関数は、idlコンパイラでXX-skelimpl.c内に生成されているはずである。
例えば、サーバントのクラス名がEchoだとすると
CORBA_Echo impl_Echo__create(PortableServer_POA poa, CORBA_Environment *ev) { CORBA_Echo retval; impl_POA_Echo *newservant; PortableServer_ObjectId objid; newservant = (impl_POA_Echo *)RtORB_calloc(1, sizeof(impl_POA_Echo)," create..."); newservant->servant.vepv = &impl_Echo_vepv; newservant->poa = poa; POA_Echo__init((PortableServer_Servant)newservant, ev); /* Before servant is going to be activated all * private attributes must be initialized. */ /* ------ init private attributes here ------ */ /* ------ ---------- end ------------- ------ */ objid = PortableServer_POA_activate_object(poa, newservant, ev); RtORB_free(objid, " objid"); retval = PortableServer_POA_servant_to_reference(poa, newservant, ev); return retval; }
となっており、Echoサーバントの生成は、
Echo myEcho = (Echo)impl_Echo__create(poa, &env);
となる。
通常のCORBAサーバントの生成手順
CORBAサーバントのRtORB内での生成プロセスは、下記の通り。
- RtORB_calloc関数でCORBAサーバントの構造体を生成し、初期化する。
- newservant->servant.vepv = &impl_Echo_vepv; を実行し、CORBAサーバントに関数定義の構造体をセットする。
- newservant->poa = poa; として、サーバントにPOAをセット。
- ''POA_Echo__init((PortableServer_Servant)newservant, ev)''; をコールして、CORBAサーバントの初期化を実施。
- その他のユーザ定義のメンバーの初期化処理
- objid = ''PortableServer_POA_activate_object(poa, newservant, ev)''; CORBAサーバントを活性化し、ObjectIdを返す。
- objidを解放する。&color(red){(この処理は、必要ないはずだがIDLコンパイラが生成している。後ほど修正)}
- retval ='' PortableServer_POA_servant_to_reference(poa, newservant, ev)''; をコールして、CORBAサーバントをCORBAオブジェクトに変換する。
- 上記で変換したCORBAオブジェクトを返り値として返す。
CORBAサーバントの初期化(POA_Echo__init)
POA_Echo__init関数は、-skels.cに定義されている。
通常は、下記のようにClassInfoの設定とサーバント構造体の初期化、RtORB_POA_Objectを生成している。
void POA_Echo__init(PortableServer_Servant servant, CORBA_Environment *env) { static PortableServer_ClassInfo class_info = { NULL, (void*(*)())&get_skel_small_Echo, "IDL:Echo:1.0", &Echo__classid, &Echo__imp }; PortableServer_ServantBase__init (((PortableServer_ServantBase *)servant), env); RtORB_POA_Object__create (&class_info, servant, NULL, NULL); }
これから分かるように、サーバントの初期化は、次の処理を行う。
- まず、PortableServer_ClassInfoを定義する。これは、repositoy_idや実装関数、クラスIDの定義等が含まれる
- ''PortableServer_ServantBase__init関数''を呼び出し、すべてのサーバントに共通な初期化を行う。
- ''RtORB_POA_Object__create関数''を呼び出し、RtORB_POA_Object構造体を生成する。このRtORB_POA_Objectは、リモート呼び出しの時に使用される。
RtORBでは、PortableServer_ClassInfo、RtORB_POA_Objectを下記のように定義している。
typedef struct { void (*dummy)(); // ダミー関数、初期化関数を入れる予定だった void *(*impl_finder)(); // メソッド名にしたがって、実装の関数ポインタを返すような関数 const char *class_name; // クラスのID(IDLファイル名から?) uint32_t *class_id; // クラスIDの整数値のはずだが、現在すべて0にセットされる。 CORBA_Class_Impl *class_impl; //クラスの実装情報、Typecode,クラス名、メッソド構造体、クラスのリポジトリIDなど }PortableServer_ClassInfo; typedef struct{ struct { void *_private; void *_vepv; } impl_serv; // サーバントの情報(ServantBaseと同じ) PortableServer_POA poa; //POAの情報 PortableServer_Servant servant; //サーバントへのポインタ? ここまので定義は、impl_POA_ServantBaseと同じ。 CORBA_Object obj; // CORBAオブジェクトへのポインタ void *_reserve; // 予備 }RtORB_POA_Object;
また、サーバントを表す構造体は、他にも
typedef void *PortableServer_Servant; typedef struct { void *_private; PortableServer_ServantBase__vepv *vepv; } PortableServer_ServantBase; typedef struct{ PortableServer_ServantBase servant; PortableServer_POA poa; void *_private; }impl_POA_ServantBase;
と定義されており、Echoの場合には、IDLコンパイラより下記のように生成されている。
typedef struct { void *_private; POA_Echo__vepv *vepv; } POA_Echo; typedef struct { POA_Echo servant; PortableServer_POA poa; /* ------ add private attributes here ------ */ /* ------ ---------- end ------------ ------ */ } impl_POA_Echo;
これから、RtORB_POA_Object構造体は、impl_POA_Echo、 impl_POA_ServantBase、PortableServer_ServantBaseにキャストすることができるようになっている。
PortableServer_ServantBase__init 関数
この関数では、引数で与えられたオブジェクトで、最低限必要なメソッドfinalize、default_POA、is_a、non_existent、add_ref、remove_refを調査し、セットされていなければ、デフォルトの関数ポインタをセットする。
RtORB_POA_Object__create関数
引数で与えられた PortableServer_ClassInfo、PortableServer_Servantを基に、RtORB_POA_Objectを生成する。
処理の流れは、下記の通り。
- 返り値となる poa_obj をRtORB_alloc関数で領域確保し、memsetですべて0に初期化する。
- poa_obj->impl_serv._private = info; 引数で与えられたPortableServer_ClassInfoの値をセット。
- poa_obj->obj = (CORBA_Object)''new_CORBA_Object(NULL)''; 新しい、CORBAオブジェクトを生成。
- poa_obj->obj->connection = ''GIOP_Connection__create()''; GIOPの接続(新規サーバーSocket)を生成。
- poa_obj->obj->_url = NULL; CORBAオブジェクトの _urlを初期化
- poa_obj->obj->num_urls = 0; CORBAオブジェクトの num_urlsを初期化
- poa_obj->obj->impl = info->class_impl; CORBAオブジェクトの implにクラスの実装情報をセット
- poa_obj->obj->typedId = (unsigned char *)RtORB_strdup(info->class_name, "RtORB_POA_Object__create"); クラス名をコピー
- poa_obj->servant = servant; poa_objとCORBAオブジェクトの servantを引数で与えられたPortableServer_Servantにセット。
- poa_obj->obj->servant = servant;
- sb->_private = poa_obj; 引数で与えられたPortableServer_Servantの _privateに生成したRtORB_POA_Objectをセット
PortableServer_POA_activate_object関数
引数で与えられた PortableServer_Servantから、PortableServer_ServantBase、RtORB_POA_Objectを生成。PortableServer_ServantBaseは、PortableServer_Servantをキャストし、RtORB_POA_Objectは、_privateにセットされているはずなので、それを使う。RtORB_POA_ObjectのobjにCORBAオブジェクトがセットされているはずなので、そこからobject_keyをObjectIdにコピーする。その後、register_PortableServer_Servant関数で、サーバントをPOAに登録する。
register_PortableServer_Servant関数
引数で与えられたPortableServer_POAのobject_mapに、PortableServer_ServantのRtORB_POA_Objectを登録する。この関数の流れは、下記の通り。
- obj = ((RtORB_POA_Object *)sb->_private)->obj; 引数で与えられたPortableServer_ServantからCORBAオブジェクトを取得。
- poa_obj = (RtORB_POA_Object *)sb->_private; 同じくRtORB_POA_Objectを取得
- IORを格納用のバファiorを確保し、初期化(1024bytes)
- ''registerItem''(poa->object_map, obj->object_key, poa_obj); POAのobject_mapに、RtORB_POA_Objectを登録。
- ''createIOR''(ior,poa->_server->sock,(char *)obj->typedId,(char *)obj->object_key); IORを生成
- obj->_ior_string = (unsigned char *)RtORB_strdup(ior, "register_PortableServer_Servant"); IORをCORBAオブジェクトにセット
- iorを開放。
PortableServer_POA_servant_to_reference関数
引数で与えられたPortableServer_ServantからCORBAオブジェクトを得て、それを返す。
この関数は、(PortabeServer_POA poa, PortableServer_Servant servant, CORBA_Environment *env)を引数としてもち、下記の処理を行う。
- sb = (PortableServer_ServantBase *)servant; 引数で与えれられたPortableServer_ServantをServentの共通表現であるPortableServer_ServantBase * にキャストする。
- poa_obj = (RtORB_POA_Object *)sb->_private; sbの最初の要素は、RtORB_POA_Object *になっているはずなので、その型にキャストする。
- return poa_obj->obj; RtORB_POA_Objectのobj要素に設定されているCORBAオブジェク卜を返り値として返す。