OmniORBのプロセス内関数呼び出しについての調査¶
omniORBがプロセス内でオブジェクトのオペレーションを呼び出す際、マーシャリングを行っているか、ネットワークを使っているか調査する。
omniidlが出力するコード
omniidlはinterfaceに対して通常以下のクラスを出力する。¶
- Hoge_Helper: ヘルパークラス?_nil, is_nil, release, duplicate, marshalObjRef, unmarshalObjRef等のstatic関数が宣言されている。
- Hoge: Hoge classインターフェース。Hoge_Helpterに加えて_pte_type, _var_type, _narrowが宣言されRepoIDへのポインタを持つ。
- _objref_Hoge: オブジェクトリファレンスクラス。CORBA::Object, omniObjRefを継承。non-copyableオブジェクト。operationが宣言されている。
- _pof_Hoge: ProxyObjectFactory? INSがらみ?
- _impl_Hoge: Hogeサーバントのスケルトン
- POA_Hoge: _impl_Hoge, ServantBase を継承。いわゆるPOAのスケルトン。通常はこちらを使う。
operationの呼び出し¶
オペレーションの呼び出しは以下の通り。
void _objref_Hoge::munya() { _0RL_cd_e6f7bc7e6deabbed_00000000 _call_desc(_0RL_lcfn_e6f7bc7e6deabbed_10000000, "munya", 6); _invoke(_call_desc); }
_0RL_cd_e6f7bc7e6deabbed_00000000 はSK.cc内で宣言されているomniCallDescriptorのサブクラス。
このオブジェクトをomniObjRef::_invoke()関数に渡している。
omniObjRef::_invoke()関数¶
omniObjRef::_invoke()はomniObjRef.ccで定義されている。
大まかな処理は以下の通り。
if( _is_nil() ) _CORBA_invoked_nil_objref(); // nilチェック call_desc.objref(this); // call_descに自身(オブジェクトリファレンス)をセット // タイムアウトに関する設定 _identity()->dispatch(call_desc); // try-catch内 // リトライしたり、ログ出力したりする
_identity()はomniObjRefの関数で、omniIdentity*を返す。
omniIdentityについて¶
omniORB4/omniInternal.hから。
_CORBA_MODULE_FN omniIdentity* createIdentity(omniIOR* ior, const char* target, _CORBA_Boolean locked); // Create an identity object that can be used to invoke operations // on the CORBA object identified by <ior>. If the object is local // and activated, the servant is checked for compatibility with // <target>. If they are compatible, the localIdentity is returned; // otherwise, an inProcessIdentity is used.
つまり、omniIdentityはローカルとリモートオブジェクトを区別している。
omniInternal.ccのomni::createIdentity()はおおよそ以下のように実装されている。
if (omniInterceptorP::createIdentity) { //インターセプタ呼び出し } // Decode the profiles const IOP::TaggedProfileList& profiles = ior->iopProfiles(); // IIOP Profileの処理 CORBA::Boolean is_local = 0; Rope* rope; // ropeはリモートオブジェクトと話すのに必要なオブジェクト。与えられたアドレスリストが // ローカルである場合、is_local が TRUE(1)にセットされ返る。 // ローカルであるとはIPアドレスおよびポート番号が一致するという意味 // 別プロセスの場合同一is_localはFALSE(0)である。 if (giopRope::selectRope(info->addresses(), info, rope, is_local) == 0) { return 0; } // IIOP Profileの選択 if (is_local) { // objectkeyのhashのリストを取得? CORBA::ULong hashv = hash(object_key.get_buffer(), object_key.length()); omni_optional_lock sync(*internalLock,locked,locked); // オブジェクトテーブルからアクティブなオブジェクトを取得? omniObjTableEntry* entry = omniObjTable::locateActive(object_key.get_buffer(), object_key.length(), hashv, 0); // entryおNULLチェックおよびダウンキャスト可能かチェック?_PD_repoIdが一致するか見ている。 if (entry && entry->servant()->_ptrToInterface(target)) { // Compatible activated object return entry; // } else { // Not active or servant incompatible with target return createInProcessIdentity(object_key.get_buffer(), object_key.length()); } } else { // Remoteの場合 holder._retn(); omni_optional_lock sync(*internalLock,locked,locked); result = new omniRemoteIdentity(ior, object_key.get_buffer(), object_key.length(), rope); return result; }
omniLocalIdentity::dispatch(omniCallDescriptor& call_desc)¶
最後にoperationを呼ぶ部分。
// ValueType型の引数をとる場合、copyValuesInLocalCallsオプションをセットすることで // もし同じ変数へのポインタが複数引数に渡された場合、コピーを省略できる。 if (call_desc.containsValues() && orbParameters::copyValuesInLocalCalls) { // Must use a call handle to call via a memory stream. if (omniORB::trace(25)) { omniORB::logger l; l << "Local call on " << this << " involves valuetypes; call via a " << "memory buffer.\n"; } omniCallHandle call_handle(&call_desc, 0); dispatch(call_handle); return; } call_desc.localId(this); omniLocalIdentity_RefHolder rh(this); omni::localInvocationCount++; pd_adapter->dispatch(call_desc, this);
dispatchは最終的に callHandle.cc の omniCallHandle::upcall(omniServant* servant, omniCallDescriptor& desc) にたどり着く。
void omniCallHandle::upcall(omniServant* servant, omniCallDescriptor& desc) { if (pd_iop_s) { // Remote call pd_iop_s->ReceiveRequest(desc); { PostInvoker postinvoker(pd_postinvoke_hook); if (!pd_mainthread_mu) { desc.doLocalCall(servant); // ローカルコール } else { // スレッドを使って呼び出し // Main thread dispatch MainThreadTask mtt(servant, desc, pd_mainthread_mu, pd_mainthread_cond); int i = _OMNI_NS(orbAsyncInvoker)->insert(&mtt); OMNIORB_ASSERT(i); mtt.wait(); } } pd_iop_s->SendReply(); }
この部分が今一つ追い切れていない。
doLocalCallは最終的に、SK.ccで定義されている↓を呼ぶ。
// Local call call-back function. static void _0RL_lcfn_e6f7bc7e6deabbed_10000000(omniCallDescriptor*, omniServant* svnt) { _impl_Hoge* impl = (_impl_Hoge*) svnt->_ptrToInterface(Hoge::_PD_repoId); impl->munya(); }