RtORBにおけるネームサーバー
RtORBに同梱されているネームサーバーについて述べます。RtORBでは、ネームサーバーは、CORBAサーバーとして実装されており、他のネームサーバーと連携して動作する機能は省略されています。また、omniNamesのように登録されているネーミングコンテキスト等をファイルに保持する機能も省かれており、終了してしまえば、それまで登録されたNameContent, Nameはすべて消失します。
以下では、RtORBで実装したネームサーバーの動作について述べる。
CosNamingインターフェース
RtORBのネームサーバーでは、CosNaming.idlで定義されているNameComponent, Name, Bindingは CosNaming.hの中で下記のように定義されています。
/* CosNaming::Istring */ typedef CORBA_string CosNaming_Istring;
/* struct CosNaming::NamingConponent */ struct CosNaming_NameComponent_type{ CosNaming_Istring id; CosNaming_Istring kind; }; typedef struct CosNaming_NameComponent_type CosNamimgNameComponent;
/* sequence<CosNaming::NamingComponent> CosNaming::Name */ struct CORBA_sequence_CosNaimg_NamingContext_type{ CORBA_unsigned_long _maximum; CORBA_unsigned_long _length; CosNaming_NameComponent *_buffer; CORBA_unsigned_long _release; } typedef struct CORBA_sequece_CosNaming_NamingContext_type CosNaming_Name;
/* enum CosNaming::BindingType */ enum { CosNaming_nobject; CosNaming_ncontext; }; typedef int CosNaming_BindingType;
/* struct CosNaming::Binding */ struct CosNaming_Binding_type{ CosNaming_Name binding_name; CosNaming_BindingType binding_type; }; typedef struct CosNaming_Binding_type CosNaming_Binding;
ネームサーバーの初期化
ネームサーバーは、main.cの中でimpl_CosNaming_NamingContext__create関数によってNamingContextが初期化される。
初期化は、以下のように行われている。
impl_CosNaming_NamingContext__create ( PortableServer_POA poa, CORBA_Environment * ev){ CORBA_CosNaming_NamingContext retval; impl_POA_CosNaming_NamingContext *newservant; PortableServer_ObjectId objid; newservant = (impl_POA_CosNaming_NamingContext *)RtORB_calloc(1, sizeof(impl_POA_CosNaming_NamingContext)," create...");引数poaに最上位のネーミングコンテキストRootContextが入り、evはエラーハンドラ。
CORBAオブジェクトを管理するネーミングコンテキストnewserverのメモリを確保・生成する。
newservant->servant.vepv = &impl_CosNaming_NamingContext_vepv; newservant->poa = poa;CORBA サーバントのメソッド関数に関する定義が格納された構造体(&impl_CosNaming_NamingContext_vepv)を設定する。
newserverにPOAを登録する。
POA_CosNaming_NamingContext__init((PortableServer_Servant)newservant, ev);
ネーミングコンテキスト・newserverを初期化する。
/* Before servant is going to be activated all * private attributes must be initialized. */ /* ------ init private attributes here ------ */ newservant->ObjectList = NULL; newservant->binding_list = NULL;
newserverを初期化する。
/* ------ ---------- end ------------- ------ */ objid = PortableServer_POA_activate_object(poa, newservant, ev);
ネーミングコンテキスト・newserverを活性化(POAに登録)する。
RtORB_free(objid, " objid");
メモリ解放する。
retval = PortableServer_POA_servant_to_reference(poa, newservant, ev);
CORBA サーバント・newservantのURLをCORBA オブジェクトに変換する。
return retval; }
impl_CosNaming_NamingContext__createはIDLコンパイラで生成されており、処理内容はimpl_Echo__createと同じです。(こちらのページを参照ください。)( http://harahome.ddo.jp/siwiki/_hara/ja/Software/CORBA%E3%82%B5%E3%83%BC%E3%83%90%E3%83%B3%E3%83%88%E3%81%AE%E7%94%9F%E6%88%90.html )
private attributesに初期化の記述が追加されています。
オブジェクト参照をネームサーバーの登録(bind)
CORBAオブジェクトをネームサーバーに登録するには、bindメソッドを呼び出せばよい。例えば、CORBAクライアントから Echoオブジェクトの登録は、
CosNaming_NamingContext_bind(namingContext, echoName, echoObj, env);
によって実行される。この例では、namingContextは、ネームサーバー上のCosNaming_NamingContext であり、echoObjは、Echoオブジェクトを表すCORBA_Object、echoNameは、echoObjを参照するためのCosNaming_Nameである。また、envは、CORBAオペレーションで発生する例外をハンドリングするためのCORBA_Environment変数である。
この関数がCORBAクライアントで実行されると、ネームサーバーでは次のような処理が行われる。
staticvoid impl_CosNaming_NamingContext_bind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Object obj, CORBA_Environment * ev){ /* ------ insert method code here ------ */ CosNaming_NameComponent *nc; CosNaming_Name *name = (CosNaming_Name *)n; PtrList **obj_list; SOCKET_LOCK(); obj_list = NamingContext__resolve_ObjectList(servant, (CosNaming_Name *)n, ev);
ネーミングコンテキストservantが持つオブジェクトリストからオブジェクト n と同じ id, kind のコンテキストを探しobj_listに返す。無ければ、ルートコンテキストをobj_listに返す。
nc = &name->_buffer[name->_length - 1];
NameComponent name->_bufferはコンテキストの名称(path)で配列で管理している。&name->_buffer の最後のバッファ=登録したいコンテキストの名称をncに設定する。
if( ContextList__find_item(*obj_list, nc) ){ fprintf(stderr, "Already binded\n"); CosNaming_AlreadyBound__set(ev); return; }ContextList__find_item関数でコンテキスト*obj_listにコンテキスト名ncがあるか確認する。確認ができれば、既にコンテキストが登録されている。エラーハンドラ ev に状態を登録しreturnする。
*obj_list = PtrList_first(BindObject__append(*obj_list, OBJECT, nc, CORBA_Object_dup(obj)));ContextList__find_item関数でコンテキスト*obj_listにコンテキスト名ncが無い時の処理。BindObject__append関数でオブジェクト nc をコンテキスト*obj_listに登録し、PtrList_first関数で*obj_listの先頭を返す。
SOCKET_UNLOCK(); /* ------ ---------- end ------------ ------ */}
オブジェクト参照をネームサーバーの再登録(rebind)
前述のbindメソッドでは、既に登録済みのエントリがあれば例外を返すが、このメソッドでは既にあるエントリに上書き登録することができる。CORBAクライアントからは、bindメソッドと同様に、
CosNaming_NamingContext_rebind(namingContext, echoName, echoObj, env);
この関数がCORBAクライアントで実行されると、ネームサーバーでは次のような処理が行われる。
static void impl_CosNaming_NamingContext_rebind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Object obj, CORBA_Environment * ev) { /* ------ insert method code here ------ */ CosNaming_NameComponent *nc, *tmp; impl_POA_CosNaming_NamingContext *contxt; PtrList **obj_list=NULL; contxt = bind_new_context(servant, n, n->_length -1, ev); SOCKET_LOCK(); obj_list = NamingContext__resolve_ObjectList(servant,(CosNaming_Name *)n,ev);ネーミングコンテキストservantが持つオブジェクトリストからオブジェクト n と同じ id, kind のコンテキストを探しobj_listに返す。無ければ、ルートコンテキストをobj_listに返す。
tmp = &n->_buffer[n->_length - 1];NameComponent name->_bufferはコンテキストの名称(path)で配列で管理している。&name->_buffer の最後のバッファ=オブジェクトを登録したいコンテキストの名をtmpに設定する。
nc = CosNaming_NameComponent__alloc(); nc->id = RtORB_strdup(tmp->id, "CosNamin:rebind"); nc->kind = RtORB_strdup(tmp->kind, "CosNamin:rebind");
上書き用コンテキストncを新たに作成し、tmp->id、tmp->kindを設定設定する。
void *itm = ContextList__find_item(*obj_list, nc);
コンテキスト*obj_listがもつオブジェクトリストからコンテキスト nc と同じid、kindのコンテキストを探しitmに返す。
if(itm == NULL){ 同一コンテキストが無かった時。 fprintf(stderr, "new bind %s/%s ",nc->id, nc->kind); *obj_list = PtrList_first(BindObject__append(*obj_list, OBJECT, nc, CORBA_Object_dup(obj))); BindObject__append関数でコンテキスト nc をコンテキスト*obj_listの最後に登録し、 PtrList_first関数で*obj_listの先頭を返す。
if(ContextList__find_item(*obj_list, nc) == NULL){ fprintf(stderr, " Fail \n"); }else{ fprintf(stderr, " Success \n"); } コンテキスト*obj_listのもつオブジェクトリストでコンテキストncと同じid、kindのオブジェクトを探し、結果を出力する。
}else{ *obj_list = PtrList_remove_item( ContextList__find_item(*obj_list, nc) );同一コンテキストがあった時。ContextList__find_item関数でコンテキスト*obj_listのオブジェクトリストから、ncと同一id、kindのコンテキストを探し、PtrList_remove_item関数でオブジェクトリストからコンテキストを削除する。
*obj_list = PtrList_first(BindObject__append(*obj_list, OBJECT, nc, CORBA_Object_dup(obj)));ひとつ前の作業で削除したコンテキスト*obj_listのポインタにコンテキスト nc を登録し、PtrList_first関数でコンテキスト*obj_listの先頭を返す。
} SOCKET_UNLOCK(); /* ------ ---------- end ------------ ------ */ }
オブジェクト参照をネームサーバーから削除(unbind)
登録済みのオブジェクト参照を削除するには、unbindメソッドを用いる。このメソッドは、CORBAクライアントからは、
CosNaming_NamingContext_unbind(namingContext, echoName, env);
で実行することができる。
この関数がCORBAクライアントで実行されると、ネームサーバーでは次のような処理が行われる。
static void impl_CosNaming_NamingContext_unbind (impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, CORBA_Environment * ev) { /* ------ insert method code here ------ */ CosNaming_NameComponent *nc; CosNaming_Name *name = (CosNaming_Name *)n; PtrList **obj_list; PtrList *tmp_item; SOCKET_LOCK(); obj_list = NamingContext__resolve_ObjectList(servant,(CosNaming_Name *)n,ev);ネーミングコンテキストservantが持つオブジェクトリストからオブジェクト n と同じ id, kind のコンテキストを探しobj_listに返す。無ければ、ルートコンテキストをobj_listに返す。
nc = &name->_buffer[name->_length - 1];NameComponent name->_bufferはコンテキストの名称(path)で配列で管理している。&name->_buffer の最後のバッファ=オブジェクトを登録したいコンテキストの名をncに設定する。
tmp_item = ContextList__find_item(*obj_list, nc); SOCKET_UNLOCK(); if( tmp_item == NULL ){ fprintf(stderr, "Unbound context.\n"); CosNaming_NotFound__set(ev, 0, name, 0); return; }コンテキスト*obj_listがもつオブジェクトリストからコンテキスト nc と同じid、kindのコンテキストを探しtmp_itemに返す。コンテキストtmp_item が確認できない時、エラーを出力し、エラーハンドル ev にCosNaming_NotFoundを登録する。
SOCKET_LOCK(); *obj_list = PtrList_first(PtrList_remove_item( tmp_item ));PtrList_remove_item関数で コンテキストtmp_itemを削除し、PtrList_first関数で*obj_listの先頭を返す。
SOCKET_UNLOCK(); /* ------ ---------- end ------------ ------ */ }
オブジェクト参照をネームサーバーに問い合わせる(resolve)
既に登録されたオブジェクト参照を、ネームサーバへ問い合わせるには、resolveメソッドを用いる。このメソッドは、CORBAクライアントからは、
CosNaming_NamingContext_resolve(namingContext, echoName, env);
で実行することができ、この関数の返り値は、該当するオブジェクトへの参照である。
この関数がCORBAクライアントで実行されると、ネームサーバーでは次のような処理が行われる。
static CORBA_Object impl_CosNaming_NamingContext_resolve (impl_POA_CosNaming_NamingContext * servant,
CosNaming_Name * n, CORBA_Environment * ev) { CORBA_Object retval; /* ------ insert method code here ------ */ BindObject *tmp; SOCKET_LOCK(); tmp = NamingContext_resolve_BindObject(servant, (CosNaming_Name *)n, n->_length, ev);コンテキストservantの持つオブジェクトリストの中から、オブジェクト n と同一コンテキストで同一id、kindトのオブジェクトを探します。
SOCKET_UNLOCK(); if(!tmp){ return NULL; } retval = CORBA_Object_dup((CORBA_Object)tmp->object); tmp->objectをretvalにコピーする。 /* ------ ---------- end ------------ ------ */ return retval; }オブジェクト tmp が確認でき無い時はNULLをreturnしimpl_CosNaming_NamingContext_resolve関数を終了する。retval = オブジェクト n と同一の情報をreturnする。
登録済みのオブジェクト参照の一覧をネームサーバーに問い合わせる(list)
ネームサーバーへは、オブジェクト参照の登録、削除だけではなくどのようなバインディング名が登録されているかの一覧を得るためのメソッドもある。これには、listメソッドを用いる。このメソッドは、CORBAクライアントからは、
CosNaming_NamingContext_list(namingContext, how_many, bindingList, bindingIterator, env);
で実行することができる。問い合わせの結果は、bindingList、bindingIteratorに格納されて返ってくるが、RtORBのネームサーバーではbindingIteratorは常にNULLになっているので注意されたい。
この関数がCORBAクライアントで実行されると、ネームサーバーでは次のような処理が行われる。
static void impl_CosNaming_NamingContext_list (impl_POA_CosNaming_NamingContext * servant, CORBA_unsigned_long how_many, CosNaming_BindingList ** bl, CosNaming_BindingIterator * bi, CORBA_Environment * ev) { /* ------ insert method code here ------ */ int i; SOCKET_LOCK(); CosNaming_BindingList *cbl = servant->binding_list; int len = PtrList_length((PtrList *)servant->ObjectList);コンテキストservant->ObjectListの要素数をlenに返す。
if(cbl == NULL || cbl->_length != len){ if(cbl == NULL){ cbl = CORBA_sequence_CosNaming_Binding__alloc(); servant->binding_list = cbl; }else{ delete_BindingList(cbl); }cblがNULLのとき、又はcblの要素数とservant->ObjectListの要素数が異なる時、ネームコンテキストserverのバインディングリストを確認し、あったら削除、無かったらメモリを確保・作成する。
if(len > 0){ cbl->_buffer = CORBA_sequence_CosNaming_Binding_allocbuf(len); バッファを確保する。 cbl->_length = cbl->_maximum = len; }else{ cbl->_buffer = NULL; cbl->_length = cbl->_maximum = 0; } for(i=0; i < len; i++){ CosNaming_Binding *cbi = &cbl->_buffer[i]; BindObject *bo; bo = (BindObject *)PtrList_get_item((PtrList *)servant->ObjectList, (int32_t)i); if(bo != NULL){ set_CosNaming_Name(&bi->binding_name, bo); if(bo->type == CONTEXT){ cbi->binding_type = CosNaming_ncontext; }else{ cbi->binding_type = CosNaming_nobject; } }else{ fprintf(stderr, "**** ERROR in NamingContext_list\n"); }lenが0より大きい時、バッファをlenの分確保し、 cbl->_length(要素数)とcbl->_maximum(最大数)をlen設定する。0以下の時、cblを初期化する。バインディングリストのバッファを確認し、あったら初期化する。オブジェクトリストのi番目の要素をboに設定する。オブジェクトリストのi番目の要素をboに設定する。要素boを確認し、bo->nameid、bo->namekindを bi(バッファ)->binding_name に設定する。オブジェクトリストの種類を設定する。要素boがNULLの時はエラー表示する。
} }
*bl = cbl; //bi = impl_CosNaming_BindingIterator__create (servant->poa, ev); bi = NULL; SOCKET_UNLOCK(); /* ------ ---------- end ------------ ------ */ }バインディングリストにcblを設定。イテレーターを初期化。
ネーミングコンテキストに関するオペレーション(new_context, bind_context, rebind_context, bind_new_context, destory)
ネーミンググラフの説明でも述べたが、ネームサーバーでは登録する名前の自由度を上げるために、ネーミングコンテキストというファイルシステムにおけるディレクトリのような概念がある。このネーミングコンテキストに関するオペレーションには、new_context, bind_context, rebind_context,bind_new_contex, destoryがある。これらのメソッドは、それぞれネームングコンテキストの生成、登録、再登録、生成し登録、削除を実行するためのメソッドである。これらの関数は、下記のようになる。
new_context
このメソッドは、
CosNaming_NamingContext_new_conext(namingContext, env );
で実行することができ、ネームサーバー内では次のような処理が行われる。
static CosNaming_NamingContext impl_CosNaming_NamingContext_new_context (impl_POA_CosNaming_NamingContext * servant, CORBA_Environment * ev) { CosNaming_NamingContext retval; /* ------ insert method code here ------ */ SOCKET_LOCK(); retval = CORBA_Object_dup(impl_CosNaming_NamingContext__create(servant->poa, ev)); SOCKET_UNLOCK(); /* ------ ---------- end ------------ ------ */ return retval; }servant->poaを登録したコンテキストを作成しretvalに設定する。
bind_context
このメソッドは、
CosNaming_NamingContext_bind_conext(namingContext, contextName, newContext, env );
で実行することができ、ネームサーバー内では次のような処理が行われる。
実装なし
rebind_context
このメソッドは、
CosNaming_NamingContext_rebind_conext( namingContext, contextName, newContext, env );
で実行することができ、ネームサーバー内では次のような処理が行われる。実装なし
bind_new_context
このメソッドは、
CosNaming_NamingContext_bind_new_conext( namingContext, contextName, env );
で実行することができ、ネームサーバー内では次のような処理が行われる。
impl_POA_CosNaming_NamingContext *bind_new_context(impl_POA_CosNaming_NamingContext * servant, CosNaming_Name * n, int depth, CORBA_Environment * ev) { int i; CosNaming_NameComponent *nc; impl_POA_CosNaming_NamingContext *srvt = servant; BindObject *bo; memset(ev, 0, sizeof(ev)); SOCKET_LOCK(); PtrList *obj_list=(PtrList *)servant->ObjectList; if(depth > n->_length || depth < 0){ depth = n->_length; } SOCKET_UNLOCK(); for(i = 0 ; i < depth; i++){ bo = NamingContext_resolve_BindObject(servant, n, i, ev); if(!bo){ SOCKET_LOCK(); CORBA_Object retval = impl_CosNaming_NamingContext__create(servant->poa, ev); nc = &n->_buffer[i];コンテキストservantのオブジェクトリストを*obj_listに設定する。depth(深さ)がn->_length(要素数)より大きい時又は、depthが0より小さい時、depthをn->_lengthに設定する。コンテキストservantとnのオブジェクトを確認し、異なるオブジェクトの時、又はContextの時は、NULLを返す。同じオブジェクトが続けば最後のオブジェクトをboに返す。boが確認できない時は、コンテキストを作成する。nのi番目のオブジェクトをncに設定する。
srvt->ObjectList = (void *)PtrList_first(BindObject__append((PtrList *)srvt->ObjectList, CONTEXT, nc, retval)); srvt = (impl_POA_CosNaming_NamingContext *)retval->servant; obj_list = (PtrList *)srvt->ObjectList; SOCKET_UNLOCK(); }else if( bo->type != CONTEXT){ fprintf(stderr, "This Name is already bounded, but it isn't contenxt..\n"); return NULL; bo->typeが }else{ SOCKET_LOCK(); CORBA_Object obj = (CORBA_Object)bo->object; srvt = (impl_POA_CosNaming_NamingContext *)obj->servant; obj_list = (PtrList *)srvt->ObjectList; SOCKET_UNLOCK(); } } return srvt; }srvt->ObjectListにncのid、kind、type=CONTEXTでretvalを登録し、先頭のオブジェクトをポイントしてsrvt->ObjectList に返す。
destory
このメソッドは、
CosNaming_NamingContext_bdestory(namingContext, env );
で実行することができ、ネームサーバー内では次のような処理が行われる。