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