Project

General

Profile

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

}