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();
}