CORBAサーバントの生成
Simple Wiki Based Contents Management System
ソフトウェア関連 >> ライブラリ >> RtORBについて >> RtORBの動作について >> CORBAサーバントの生成

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内での生成プロセスは、下記の通り。
  1. RtORB_calloc関数でCORBAサーバントの構造体を生成し、初期化する。
  2. newservant->servant.vepv = &impl_Echo_vepv; を実行し、CORBAサーバントに関数定義の構造体をセットする。
  3. newservant->poa = poa; として、サーバントにPOAをセット。
  4. POA_Echo__init((PortableServer_Servant)newservant, ev); をコールして、CORBAサーバントの初期化を実施。
  5. その他のユーザ定義のメンバーの初期化処理
  6. objid = PortableServer_POA_activate_object(poa, newservant, ev); CORBAサーバントを活性化し、ObjectIdを返す。
  7. objidを解放する。&color(red){(この処理は、必要ないはずだがIDLコンパイラが生成している。後ほど修正)}
  8. retval = PortableServer_POA_servant_to_reference(poa, newservant, ev); をコールして、CORBAサーバントをCORBAオブジェクトに変換する。
  9. 上記で変換した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);
}
これから分かるように、サーバントの初期化は、次の処理を行う。
  1. まず、PortableServer_ClassInfoを定義する。これは、repositoy_idや実装関数、クラスIDの定義等が含まれる
  2. PortableServer_ServantBase__init関数を呼び出し、すべてのサーバントに共通な初期化を行う。
  3. 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を生成する。
処理の流れは、下記の通り。
  1. 返り値となる poa_obj をRtORB_alloc関数で領域確保し、memsetですべて0に初期化する。
  2. poa_obj->impl_serv._private = info; 引数で与えられたPortableServer_ClassInfoの値をセット。
  3. poa_obj->obj = (CORBA_Object)new_CORBA_Object(NULL); 新しい、CORBAオブジェクトを生成。
  4. poa_obj->obj->connection = GIOP_Connection__create(); GIOPの接続(新規サーバーSocket)を生成。
  5. poa_obj->obj->_url = NULL; CORBAオブジェクトの _urlを初期化
  6. poa_obj->obj->num_urls = 0; CORBAオブジェクトの num_urlsを初期化
  7. poa_obj->obj->impl = info->class_impl; CORBAオブジェクトの implにクラスの実装情報をセット
  8. poa_obj->obj->typedId = (unsigned char *)RtORB_strdup(info->class_name, "RtORB_POA_Object__create"); クラス名をコピー
  9. poa_obj->servant = servant; poa_objとCORBAオブジェクトの servantを引数で与えられたPortableServer_Servantにセット。
  10. poa_obj->obj->servant = servant;
  11. 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を登録する。この関数の流れは、下記の通り。
  1. obj = ((RtORB_POA_Object *)sb->_private)->obj; 引数で与えられたPortableServer_ServantからCORBAオブジェクトを取得。
  2. poa_obj = (RtORB_POA_Object *)sb->_private;  同じくRtORB_POA_Objectを取得
  3. IORを格納用のバファiorを確保し、初期化(1024bytes)
  4. registerItem(poa->object_map, obj->object_key, poa_obj); POAのobject_mapに、RtORB_POA_Objectを登録。
  5. createIOR(ior,poa->_server->sock,(char *)obj->typedId,(char *)obj->object_key); IORを生成
  6. obj->_ior_string = (unsigned char *)RtORB_strdup(ior, "register_PortableServer_Servant"); IORをCORBAオブジェクトにセット
  7. iorを開放。

PortableServer_POA_servant_to_reference関数

引数で与えられたPortableServer_ServantからCORBAオブジェクトを得て、それを返す。
この関数は、(PortabeServer_POA poa, PortableServer_Servant servant, CORBA_Environment *env)を引数としてもち、下記の処理を行う。
  1. sb = (PortableServer_ServantBase *)servant; 引数で与えれられたPortableServer_ServantをServentの共通表現であるPortableServer_ServantBase * にキャストする。
  2. poa_obj = (RtORB_POA_Object *)sb->_private; sbの最初の要素は、RtORB_POA_Object *になっているはずなので、その型にキャストする。
  3. return poa_obj->obj;  RtORB_POA_Objectのobj要素に設定されているCORBAオブジェク卜を返り値として返す。