📄 giopbidir.cc
字号:
// -*- Mode: C++; -*-// Package : omniORB2// giopBiDir.cc Created on: 17/7/2001// Author : Sai Lai Lo (sll)//// Copyright (C) 2001 AT&T Laboratories Cambridge//// This file is part of the omniORB library//// The omniORB library is free software; you can redistribute it and/or// modify it under the terms of the GNU Library General Public// License as published by the Free Software Foundation; either// version 2 of the License, or (at your option) any later version.//// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Library General Public License for more details.//// You should have received a copy of the GNU Library General Public// License along with this library; if not, write to the Free// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA// 02111-1307, USA////// Description:// *** PROPRIETORY INTERFACE ***///* $Log: giopBiDir.cc,v $ Revision 1.1.2.20 2005/03/02 13:25:39 dgrisby Variable name clash. Revision 1.1.2.19 2005/01/29 17:25:03 dgrisby Memory leaks in bidir connection management. Revision 1.1.2.18 2004/10/18 00:23:54 dgrisby Bug in trying to set up bidirectional GIOP with GIOP 1.0 and 1.1. Revision 1.1.2.17 2004/05/25 16:25:18 dgrisby Typo in bidir changes. Revision 1.1.2.16 2004/05/25 14:02:22 dgrisby Properly close bidirectional connections. Revision 1.1.2.15 2003/02/03 16:53:14 dgrisby Force type in constructor argument to help confused compilers. Revision 1.1.2.14 2002/11/26 14:51:50 dgrisby Implement missing interceptors. Revision 1.1.2.13 2002/08/23 14:15:02 dgrisby Avoid exception with bidir when no POA. Revision 1.1.2.12 2002/08/21 06:23:15 dgrisby Properly clean up bidir connections and ropes. Other small tweaks. Revision 1.1.2.11 2002/01/16 11:31:59 dpg1 Race condition in use of registerNilCorbaObject/registerTrackedObject. (Reported by Teemu Torma). Revision 1.1.2.10 2001/11/08 16:31:19 dpg1 Minor tweaks. Revision 1.1.2.9 2001/09/19 17:26:49 dpg1 Full clean-up after orb->destroy(). Revision 1.1.2.8 2001/09/10 17:45:22 sll Call stopIdleCounter when a strand is switched to bidirectional in getBiDirServiceContext. Revision 1.1.2.7 2001/09/03 17:32:05 sll Make sure that acquireClient honours the deadline set in the calldescriptor. Revision 1.1.2.6 2001/08/29 17:52:03 sll Consult serverTransportRule to decide whether to accept the switch to bidirectional on the server side. Revision 1.1.2.5 2001/08/23 10:11:53 sll Initialise BiDirPolicy constants properly for compilers with no namespace support. Revision 1.1.2.4 2001/08/21 11:02:14 sll orbOptions handlers are now told where an option comes from. This is necessary to process DefaultInitRef and InitRef correctly. Revision 1.1.2.3 2001/08/17 17:12:36 sll Modularise ORB configuration parameters. Revision 1.1.2.2 2001/07/31 17:31:40 sll strchr returns const char*. Revision 1.1.2.1 2001/07/31 16:10:38 sll Added GIOP BiDir support. */#include <omniORB4/CORBA.h>#include <omniORB4/minorCode.h>#include <omniORB4/omniInterceptors.h>#include <omniORB4/objTracker.h>#include <exceptiondefs.h>#include <giopStrand.h>#include <giopRope.h>#include <giopBiDir.h>#include <giopStreamImpl.h>#include <giopStream.h>#include <GIOP_C.h>#include <GIOP_S.h>#include <giopServer.h>#include <initialiser.h>#include <objectAdapter.h>#include <tcp/tcpTransportImpl.h>#include <orbOptions.h>#include <orbParameters.h>#include <transportRules.h>OMNI_USING_NAMESPACE(omni)// XXX To-do// a) BiDirServerRope garbage collection. At the moment, the server// side of a bidirectional connection is garbage collected in// the same way as an ordinary connection. That is, it is closed after// a period of inactivity. In fact, the connection should only be closed// if all the object references unmarshal from the connection have// been released. In other words, the reference count on the// BiDirServerRope instance attached to the connection == 0.////////////////////////////////////////////////////////////////////////////// Configuration options //////////////////////////////////////////////////////////////////////////////CORBA::Boolean orbParameters::acceptBiDirectionalGIOP = 0;// Applies to the server side. Set to 1 to indicates that the// ORB may choose to accept a clients offer to use bidirectional// GIOP calls on a connection. Set to 0 means the ORB should// never accept any bidirectional offer and should stick to normal// GIOP.//// Valid values = 0 or 1CORBA::Boolean orbParameters::offerBiDirectionalGIOP = 0;// Applies to the client side. Set to 1 to indicates that the// ORB may choose to use a connection to do bidirectional GIOP// calls. Set to 0 means the ORB should never do bidirectional.//// Valid values = 0 or 1////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////#if defined(HAS_Cplusplus_Namespace) && defined(_MSC_VER)// MSVC++ does not give the variables external linkage otherwise. Its a bug.namespace BiDirPolicy {_init_in_def_( const CORBA::PolicyType BIDIRECTIONAL_POLICY_TYPE = 37; )_init_in_def_( const BidirectionalPolicyValue NORMAL = 0; )_init_in_def_( const BidirectionalPolicyValue BOTH = 1; )}#else_init_in_def_( const CORBA::PolicyType BiDirPolicy::BIDIRECTIONAL_POLICY_TYPE = 37; )_init_in_def_( const BiDirPolicy::BidirectionalPolicyValue BiDirPolicy::NORMAL = 0; )_init_in_def_( const BiDirPolicy::BidirectionalPolicyValue BiDirPolicy::BOTH = 1; )#endifBiDirPolicy::BidirectionalPolicy::~BidirectionalPolicy() {}CORBA::Policy_ptrBiDirPolicy::BidirectionalPolicy::copy(){ if( _NP_is_nil() ) _CORBA_invoked_nil_pseudo_ref(); return new BidirectionalPolicy(pd_value);}void*BiDirPolicy::BidirectionalPolicy::_ptrToObjRef(const char* repoId){ OMNIORB_ASSERT(repoId ); if( omni::ptrStrMatch(repoId, BiDirPolicy::BidirectionalPolicy::_PD_repoId) ) return (BiDirPolicy::BidirectionalPolicy_ptr) this; if( omni::ptrStrMatch(repoId, CORBA::Policy::_PD_repoId) ) return (CORBA::Policy_ptr) this; if( omni::ptrStrMatch(repoId, CORBA::Object::_PD_repoId) ) return (CORBA::Object_ptr) this; return 0;}BiDirPolicy::BidirectionalPolicy_ptrBiDirPolicy::BidirectionalPolicy::_duplicate(BiDirPolicy::BidirectionalPolicy_ptr obj){ if( !CORBA::is_nil(obj) ) obj->_NP_incrRefCount(); return obj;}BiDirPolicy::BidirectionalPolicy_ptrBiDirPolicy::BidirectionalPolicy::_narrow(CORBA::Object_ptr obj){ if( CORBA::is_nil(obj) ) return _nil(); BidirectionalPolicy_ptr p = (BidirectionalPolicy_ptr) obj->_ptrToObjRef(BidirectionalPolicy::_PD_repoId); if( p ) p->_NP_incrRefCount(); return p ? p : _nil();}BiDirPolicy::BidirectionalPolicy_ptrBiDirPolicy::BidirectionalPolicy::_nil(){ static BidirectionalPolicy* _the_nil_ptr = 0; if( !_the_nil_ptr ) { omni::nilRefLock().lock(); if( !_the_nil_ptr ) { _the_nil_ptr = new BidirectionalPolicy; registerNilCorbaObject(_the_nil_ptr); } omni::nilRefLock().unlock(); } return _the_nil_ptr;}const char*BiDirPolicy::BidirectionalPolicy::_PD_repoId = "IDL:omg.org/BiDirPolicy/BidirectionalPolicy:1.0";////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////OMNI_NAMESPACE_BEGIN(omni)////////////////////////////////////////////////////////////////////////typedef _CORBA_Unbounded_Sequence<IIOP::Address> ListenPointList;////////////////////////////////////////////////////////////////////////RopeLink BiDirServerRope::ropes;////////////////////////////////////////////////////////////////////////BiDirServerRope::BiDirServerRope(giopStrand* strand, giopAddress* addr) : giopRope(addr,0), pd_sendfrom((const char*)strand->connection->peeraddress()) { pd_maxStrands = 1; pd_oneCallPerConnection = 0; strand->RopeLink::insert(pd_strands);}////////////////////////////////////////////////////////////////////////BiDirServerRope::~BiDirServerRope(){ giopAddressList::const_iterator i, last; i = pd_redirect_addresses.begin(); last = pd_redirect_addresses.end(); for (; i != last; i++) { delete (*i); }}////////////////////////////////////////////////////////////////////////BiDirServerRope*BiDirServerRope::addRope(giopStrand* strand, const giopAddressList& addrlist) { ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,1); OMNIORB_ASSERT(!strand->isClient() && strand->biDir == 1); const char* sendfrom = strand->connection->peeraddress(); BiDirServerRope* br = 0; // Check if there already exists a rope for the strand. RopeLink* p = BiDirServerRope::ropes.next; while ( p != &BiDirServerRope::ropes ) { br = (BiDirServerRope*)p; if (strcmp(sendfrom,br->pd_sendfrom) == 0) { break; } else if (br->pd_refcount == 0 && RopeLink::is_empty(br->pd_strands) && !br->pd_nwaiting) { // garbage rope, remove it p = p->next; br->RopeLink::remove(); delete br; } else { p = p->next; } br = 0; } if (!br) { giopAddress* addr = giopAddress::str2Address(strand->connection->peeraddress()); br = new BiDirServerRope(strand,addr); br->RopeLink::insert(BiDirServerRope::ropes); } giopAddressList::const_iterator i, last; i = addrlist.begin(); last = addrlist.end(); for (; i != last; i++) { CORBA::Boolean matched = 0; giopAddressList::const_iterator j, k; j = br->pd_redirect_addresses.begin(); k = br->pd_redirect_addresses.end(); for (; j != k; j++) { if (omni::ptrStrMatch((*i)->address(),(*j)->address())) { matched = 1; break; } } if (!matched) { giopAddress* a = (*i)->duplicate(); br->pd_redirect_addresses.push_back(a); } } return br;}////////////////////////////////////////////////////////////////////////intBiDirServerRope::selectRope(const giopAddressList& addrlist, omniIOR::IORInfo* info, Rope*& r) { ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,1); const char* sendfrom = 0; omniIOR::IORExtraInfoList& cinfo = info->extraInfo(); for (CORBA::ULong index = 0; index < cinfo.length(); index++) { if (cinfo[index]->compid == IOP::TAG_OMNIORB_BIDIR) { sendfrom = ((BiDirInfo*)cinfo[index])->sendfrom; break; } } if (!sendfrom) return 0; GIOP::Version v = info->version(); // Only GIOP 1.2 IORs can do bidirectional calls. if (v.major != 1 || v.minor < 2) return 0; BiDirServerRope* br; RopeLink* p = BiDirServerRope::ropes.next; while ( p != &BiDirServerRope::ropes ) { br = (BiDirServerRope*)p; if (br->match(sendfrom,addrlist)) { br->realIncrRefCount(); r = (Rope*)br; return 1; } else if (br->pd_refcount == 0 && RopeLink::is_empty(br->pd_strands) && !br->pd_nwaiting) { // garbage rope, remove it p = p->next; br->RopeLink::remove(); delete br; } else { p = p->next; } } // Reach here because we cannot find a match. return 0;}////////////////////////////////////////////////////////////////////////CORBA::BooleanBiDirServerRope::match(const char* sendfrom, const giopAddressList& addrlist) const { if (strcmp(pd_sendfrom,sendfrom) != 0) return 0; giopAddressList::const_iterator i, last; i = addrlist.begin(); last = addrlist.end(); for (; i != last; i++) { giopAddressList::const_iterator j, k; j = pd_redirect_addresses.begin(); k = pd_redirect_addresses.end(); for (; j != k; j++) { if (omni::ptrStrMatch((*i)->address(),(*j)->address())) return 1; } } return 0;}////////////////////////////////////////////////////////////////////////IOP_C*BiDirServerRope::acquireClient(const omniIOR* ior, const CORBA::Octet* key, CORBA::ULong keysize, omniCallDescriptor* calldesc) { GIOP::Version v = ior->getIORInfo()->version(); giopStreamImpl* impl = giopStreamImpl::matchVersion(v); if (!impl) { impl = giopStreamImpl::maxVersion(); v = impl->version(); } // Only use this connection to do calls with GIOP 1.2 or above. OMNIORB_ASSERT(v.major > 1 || v.minor >= 2); ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,0); omni_tracedmutex_lock sync(*omniTransportLock); OMNIORB_ASSERT(!pd_oneCallPerConnection && pd_maxStrands == 1); giopStrand* s = 0; if (pd_strands.next != &pd_strands) { s = (giopStrand*)(pd_strands.next); } if (!s || s->state() == giopStrand::DYING) { // We no longer have a working bidirectional connection. OMNIORB_THROW(TRANSIENT,TRANSIENT_BiDirConnIsGone,CORBA::COMPLETED_NO); } OMNIORB_ASSERT(s->state() == giopStrand::ACTIVE); // We do not check what GIOP version(s) the strand has been used for // previously. If ever we have 2 calls using 2 different versions // (and both are 1.2 or above), we allow this to happen. Contrast // this with the algorithm in giopRope::acquireClient. GIOP_C* g; if (!giopStreamList::is_empty(s->clients)) { giopStreamList* gp = s->clients.next; for (; gp != &s->clients; gp = gp->next) { g = (GIOP_C*)gp; if (g->state() == IOP_C::UnUsed) { g->impl(impl); g->initialise(ior,key,keysize,calldesc); return g; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -