gioprope.cc

来自「编译工具」· CC 代码 · 共 883 行 · 第 1/2 页

CC
883
字号
// -*- Mode: C++; -*-//                            Package   : omniORB// giopRope.cc                Created on: 16/01/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:///*  $Log: giopRope.cc,v $  Revision 1.1.4.28  2005/10/17 15:50:55  dgrisby  Permit clients to scavenge bidir connections if no object references  have been transmitted.  Revision 1.1.4.27  2005/08/23 11:46:05  dgrisby  Race condition in strand selection could lead to an assertion failure.  Revision 1.1.4.26  2004/12/20 20:13:21  dgrisby  Log when switching addresses in a rope.  Revision 1.1.4.25  2003/09/25 13:12:20  dgrisby  Correctly complain if some parameters are set to zero.  Revision 1.1.4.24  2003/06/02 09:28:22  dgrisby  Segfault in log message when throwing an exception in an interceptor.  Revision 1.1.4.23  2003/02/17 01:20:00  dgrisby  Avoid deadlock with bidir connection shutdown.  Revision 1.1.4.22  2002/09/08 21:12:38  dgrisby  Properly handle IORs with no usable profiles.  Revision 1.1.4.21  2002/08/23 14:15:02  dgrisby  Avoid exception with bidir when no POA.  Revision 1.1.4.20  2002/03/18 15:13:08  dpg1  Fix bug with old-style ORBInitRef in config file; look for  -ORBtraceLevel arg before anything else; update Windows registry  key. Correct error message.  Revision 1.1.4.19  2001/09/19 17:26:49  dpg1  Full clean-up after orb->destroy().  Revision 1.1.4.18  2001/09/10 17:47:17  sll  startIdleCounter when the strand is definitely idle.  Revision 1.1.4.17  2001/09/04 14:40:30  sll  Added the boolean argument to notifyCommFailure to indicate if  omniTransportLock is held by the caller.  Revision 1.1.4.16  2001/09/03 17:31:52  sll  Make sure that acquireClient honours the deadline set in the calldescriptor.  Revision 1.1.4.15  2001/09/03 13:31:45  sll  Removed debug trace.  Revision 1.1.4.14  2001/09/03 13:26:35  sll  In filterAndSortAddressList, change to use the lowest value to represent  the highest priority.  Revision 1.1.4.13  2001/08/31 11:57:16  sll  Client side transport selection is now determined by the clientTransportRules.  Revision 1.1.4.12  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.4.11  2001/08/17 17:12:37  sll  Modularise ORB configuration parameters.  Revision 1.1.4.10  2001/08/06 15:50:27  sll  In filterAndSortAddressList, make unix transport as the first choice if  available. This is just a temporary solution until we have table driven  transport selection.  Revision 1.1.4.9  2001/08/03 17:41:21  sll  System exception minor code overhaul. When a system exeception is raised,  a meaning minor code is provided.  Revision 1.1.4.8  2001/08/01 18:12:54  sll  In filterAndSortAddressList, use_bidir could be left uninitialised.  Revision 1.1.4.7  2001/07/31 16:24:23  sll  Moved filtering and sorting of available addresses into a separate  function. Make acquireClient, decrRefCount and notifyCommFailure virtual.  Revision 1.1.4.6  2001/07/13 15:26:58  sll  Use safeDelete to remove a strand.  Revision 1.1.4.5  2001/06/13 20:13:15  sll  Minor updates to make the ORB compiles with MSVC++.  Revision 1.1.4.4  2001/06/11 18:01:58  sll  Temporarily hardwared to choose ssl over tcp transport if the IOR has both.  Revision 1.1.4.3  2001/05/31 16:18:13  dpg1  inline string matching functions, re-ordered string matching in  _ptrToInterface/_ptrToObjRef  Revision 1.1.4.2  2001/05/08 17:06:53  sll  Client side now closes the connection if it encounters any error in  processing a call.  Revision 1.1.4.1  2001/04/18 18:10:49  sll  Big checkin with the brand new internal APIs.  */#include <omniORB4/CORBA.h>#include <omniORB4/IOP_C.h>#include <giopRope.h>#include <giopStream.h>#include <giopStrand.h>#include <giopStreamImpl.h>#include <giopBiDir.h>#include <GIOP_C.h>#include <objectAdapter.h>#include <exceptiondefs.h>#include <omniORB4/minorCode.h>#include <initialiser.h>#include <orbOptions.h>#include <orbParameters.h>#include <transportRules.h>#include <omniORB4/callDescriptor.h>#include <stdlib.h>OMNI_NAMESPACE_BEGIN(omni)//////////////////////////////////////////////////////////////////////////////             Configuration options                                      //////////////////////////////////////////////////////////////////////////////CORBA::Boolean orbParameters::oneCallPerConnection = 1;//  1 means only one call can be in progress at any time per connection.////  Valid values = 0 or 1CORBA::ULong orbParameters::maxGIOPConnectionPerServer = 5;//  The ORB could open more than one connections to a server//  depending on the number of concurrent invocations to the same//  server. This variable decide what is the maximum number of//  connections to use per server. This variable is read only once//  at ORB_init. If the number of concurrent invocations exceed this//  number, the extra invocations would be blocked until the//  the outstanding ones return.////  Valid values = (n >= 1) ///////////////////////////////////////////////////////////////////////RopeLink giopRope::ropes;////////////////////////////////////////////////////////////////////////giopRope::giopRope(const giopAddressList& addrlist,		   const omnivector<CORBA::ULong>& preferred) :  pd_refcount(0),  pd_address_in_use(0),  pd_maxStrands(orbParameters::maxGIOPConnectionPerServer),  pd_oneCallPerConnection(orbParameters::oneCallPerConnection),  pd_nwaiting(0),  pd_cond(omniTransportLock){  {    giopAddressList::const_iterator i, last;    i    = addrlist.begin();    last = addrlist.end();    for (; i != last; i++) {      giopAddress* a = (*i)->duplicate();      pd_addresses.push_back(a);    }  }  {    omnivector<CORBA::ULong>::const_iterator i, last;    i    = preferred.begin();    last = preferred.end();    for (; i != last; i++) {      pd_addresses_order.push_back(*i);    }  }}////////////////////////////////////////////////////////////////////////giopRope::giopRope(giopAddress* addr,int initialRefCount) :  pd_refcount(initialRefCount),  pd_address_in_use(0),  pd_maxStrands(orbParameters::maxGIOPConnectionPerServer),  pd_oneCallPerConnection(orbParameters::oneCallPerConnection),  pd_nwaiting(0),  pd_cond(omniTransportLock){  pd_addresses.push_back(addr);  pd_addresses_order.push_back(0);}////////////////////////////////////////////////////////////////////////giopRope::~giopRope() {  OMNIORB_ASSERT(pd_nwaiting == 0);  giopAddressList::iterator i, last;  i    = pd_addresses.begin();  last = pd_addresses.end();  for (; i != last; i++) {    delete (*i);  }}////////////////////////////////////////////////////////////////////////IOP_C*giopRope::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();  }  ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,0);  omni_tracedmutex_lock sync(*omniTransportLock); again:  unsigned int nbusy = 0;  unsigned int ndying = 0;  unsigned int nwrongver = 0;  CORBA::ULong max = pd_maxStrands;  // snap the value now as it may                                     // change by the application anytime.  RopeLink* p = pd_strands.next;  for (; p != &pd_strands; p = p->next) {    giopStrand* s = (giopStrand*)p;    switch (s->state()) {    case giopStrand::DYING:      {	// Bidirectional strands do not count towards the total of	// dying strands. This is because with a bidirectional rope,	// the max number of strands is one. Below, if the number of	// dying strands is > the max, we wait for the strands to die.	// However, it is possible that we are the client keeping the	// strand alive, leading to a deadlock. To avoid the	// situation, we do not count dying bidir strands, allowing us	// to create a new one, and release the one that is dying.	if (!s->biDir)	  ndying++;	break;      }    case giopStrand::TIMEDOUT:      {	s->StrandList::remove();	s->state(giopStrand::ACTIVE);	s->StrandList::insert(giopStrand::active);	// falls through      }    case giopStrand::ACTIVE:      {	if (s->version.major != v.major || s->version.minor != v.minor) {	  // Wrong GIOP version. Each strand can only be used	  // for one GIOP version.	  // If ever we allow more than one GIOP version	  // to use one strand, make sure the client side interceptor	  // for codeset is updated to reflect this.	  nwrongver++;	}	else {	  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->initialise(ior,key,keysize,calldesc);		return g;	      }	    }	    nbusy++;	  }	  else {	    g = new GIOP_C(this,s);	    g->impl(s->giopImpl);	    g->initialise(ior,key,keysize,calldesc);	    g->giopStreamList::insert(s->clients);	    return g;	  }	}      }    }  }  // Reach here if we haven't got a strand to grab a GIOP_C.  if ((nbusy + ndying) < max) {    // Create a new strand.    // Notice that we can have up to    //  pd_maxStrands * <no. of supported GIOP versions> strands created.    //        // Do a sanity check here. It could be the case that this rope has    // no valid address to use. This can be the case if we have    // unmarshalled an IOR which has no profiles we can support. In    // theory it shouldn't happen because all IORs must support IIOP.    // However, this could be a special ORB version in which the IIOP    // transport is taken out. Notice that we do not raise an    // exception at the time when the IOR was unmarshalled because we    // would like to be able to receive and pass along object    // references that we ourselves cannot talk to.    if (pd_addresses_order.empty()) {      OMNIORB_THROW(TRANSIENT,TRANSIENT_NoUsableProfile,CORBA::COMPLETED_NO);    }    giopStrand* s = new giopStrand(pd_addresses[pd_addresses_order[pd_address_in_use]]);    s->state(giopStrand::ACTIVE);    s->RopeLink::insert(pd_strands);    s->StrandList::insert(giopStrand::active);    s->version = v;    s->giopImpl = impl;  }  else if (pd_oneCallPerConnection || ndying >= max) {    // Wait for a strand to be unused.    pd_nwaiting++;    unsigned long deadline_secs,deadline_nanosecs;    calldesc->getDeadline(deadline_secs,deadline_nanosecs);    if (deadline_secs || deadline_nanosecs) {      if (pd_cond.timedwait(deadline_secs,deadline_nanosecs) == 0) {	pd_nwaiting--;	OMNIORB_THROW(TRANSIENT,TRANSIENT_CallTimedout,CORBA::COMPLETED_NO);      }    }    else {      pd_cond.wait();    }    pd_nwaiting--;  }  else {    // Pick a random non-dying strand.    OMNIORB_ASSERT(nbusy);  // There must be a non-dying strand that can                            // serve this GIOP version    int n = rand() % nbusy;    // Pick a random and non-dying strand    RopeLink* p = pd_strands.next;    giopStrand* q = 0;    giopStrand* s = 0;    while (n >=0 && p != &pd_strands) {      s = (giopStrand*)p;      if (s->state() == giopStrand::ACTIVE &&	  s->version.major == v.major &&	  s->version.minor == v.minor)	{	  n--;	  if (!q) q = s;	}      else {	s = 0;      }      p = p->next;    }    s = (s) ? s : q;    // By the time we look for busy strands, it's possible that they    // are all dying, in which case we have to start again.    if (s) {      GIOP_C* g = new GIOP_C(this,s);      g->impl(s->giopImpl);      g->initialise(ior,key,keysize,calldesc);      g->giopStreamList::insert(s->clients);      return g;    }  }  goto again;}////////////////////////////////////////////////////////////////////////voidgiopRope::releaseClient(IOP_C* iop_c) {  ASSERT_OMNI_TRACEDMUTEX_HELD(*omniTransportLock,0);  omni_tracedmutex_lock sync(*omniTransportLock);  GIOP_C* giop_c = (GIOP_C*) iop_c;  giop_c->rdUnLock();  giop_c->wrUnLock();  // We decide in the following what to do with this GIOP_C and the strand  // it is attached:  //  // 1. If the strand is used simultaneously for multiple calls, it will have  //    multiple GIOP_Cs attached. We only want to keep at most 1 idle GIOP_C.  //    In other words, if this is not the last GIOP_C attached to the strand  //    we delete it. (Actually it does no harm to delete all GIOP_C  //    irrespectively. It will be slower to do an invocation because a  //    new GIOP_C has to be instantiated in every call.  //  // 2. If the strand is in the DYING state, we obviously should delete the  //    GIOP_C. If this is also the last GIOP_C, we delete the strand as  //    well. If the strand is used to support bidirectional GIOP, we  //    also check to ensure that the GIOP_S list is empty.  //  giopStrand* s = &((giopStrand&)(*(giopStream*)giop_c));  giop_c->giopStreamList::remove();  CORBA::Boolean remove = 0;  CORBA::Boolean avail = 1;  if (giop_c->state() != IOP_C::Idle && s->state() != giopStrand::DYING ) {    s->state(giopStrand::DYING);    if (omniORB::trace(30)) {      omniORB::logger l;      if (s->connection) {	l << "Unexpected error encountered in talking to the server "	  << s->connection->peeraddress()	  << " . The connection is closed immediately.\n";      }      else {	OMNIORB_ASSERT(s->address);	l << "Unexpected error encountered before talking to the server "	  << s->address->address()

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?